gitlab.com/sparetimecoders/build-tools@v0.1.0/README.md (about)

     1  
     2  # build-tools
     3  A set of highly opinionated tools for creating and building components/services into [docker](https://www.docker.com/) images and deploying them to [Kubernetes](https://kubernetes.io/) clusters.
     4  
     5  By following the conventions set by the tools, building and deploying applications is made simpler.
     6  
     7  The only hard requirement is to provide a [Dockerfile](https://docs.docker.com/engine/reference/builder/) which describes how to build and run your application.
     8  
     9  The configuration needed is done by environment variables (most likely for CI/CD) and yaml files (for local use).
    10  
    11  # Available commands
    12  
    13  ## build
    14  ## push
    15  ## deploy
    16  
    17  # Conventions
    18  
    19  * `Dockerfile` must be present in the root of the project directory (*TODO Override name of file*). The `Dockerfile` will be used to build the project into a runnable docker image.
    20  * The name of the directory will be used as the name of the docker image (*TODO Override by ENV*)
    21  * The current commit id will be used as docker tag
    22  * Kubernetes descriptor files must be located in the `k8s` folder under the root
    23  
    24  Take a look at the build-tools-example repository (*TODO link*) to try it out.
    25  
    26  ## Using in CI/CD pipelines
    27  
    28  ## Example usage
    29  After installing (*TODO link*) the tools, clone the build-tools-example repository (*TODO link*), cd into it and execute the `build` command.
    30  
    31      $ build
    32      Using CI none
    33      
    34      no Docker registry found
    35  
    36  Since we we haven't setup a`.buildtools.yaml` (*TODO LINK in doc*) file, nothing has been configured, and to be able to build a docker image we must specify where we (potentially) want to push it later. In other words, setting the [tags](https://docs.docker.com/engine/reference/commandline/tag/) of the created image.
    37  Luckily we can use environment variables as well, let's try:
    38  
    39      $ DOCKERHUB_REPOSITORY=sparetimecoders build
    40      Using CI none
    41      
    42      Using registry Dockerhub
    43  
    44      Login Succeeded
    45      Using build variables commit 7c76db502b4a70df5480d6ff438ae10e374b420e on branch master
    46  
    47  As we can see, the `build` command identified that we are using Dockerhub, and extracted the commit id and branch information from the local git repository.
    48  Notice that the name of the current directory is used as the image name.
    49  After the successful build the image is tagged with the commit id and branch.
    50  
    51      Successfully tagged sparetimecoders/buildtools-examples:7c76db502b4a70df5480d6ff438ae10e374b420e
    52      Successfully tagged sparetimecoders/buildtools-examples:master
    53      Successfully tagged sparetimecoders/buildtools-examples:latest
    54  
    55  
    56  
    57      
    58  Now that we have a docker image, let's publish it to the docker repository (this of course requires write access to the repository).
    59  
    60      $ DOCKERHUB_REPOSITORY=sparetimecoders DOCKERHUB_PASSWORD=<PASSWORD> DOCKERHUB_USERNAME=<USERNAME> push
    61      ...
    62      Pushing tag 'sparetimecoders/buildtools-examples:7c76db502b4a70df5480d6ff438ae10e374b420e'
    63      ...
    64  
    65      
    66      
    67      
    68  *TODO Link to more environment variables and stuff*
    69  
    70  ## Basic setup
    71  - Clone this repository
    72  - Add `BUILD_TOOLS_PATH=<PATH TO THIS REPOSITORY>` to your shell environment, typically in `.bash_profile` or something similar
    73  
    74  
    75  ## Setup script
    76  Script to be used for scaffolding a component/service. Handles repository, build-pipeline and basic files-scaffolding.
    77  
    78      ${BUILD_TOOLS_PATH}/service-setup --stack <stack> <name>
    79  
    80  See [Build project structure](#Build-project-structure) below
    81  
    82  ## Common build scripts
    83  Scripts to be used for building and deploying our services (typically when running in a CI/CD environment). They can also be used for local builds/deploy.
    84  
    85      ${BUILD_TOOLS_PATH}/build
    86      ${BUILD_TOOLS_PATH}/push
    87  
    88  ## Build project structure
    89  Configuration and setup is done in `.buildtools` files. Those files must be present in the project folder or upwards in the dicectory structure. This lets you create a common `.buildtools` file to be used for a set of projects.
    90  Example:
    91  
    92      $ pwd
    93      ~/source/
    94      $ tree
    95      .
    96      ├── customer1
    97      │   ├── project1
    98      │   └── project2
    99      └── customer2
   100          └── project1
   101          
   102  Here we can choose to put a `.buildtools` file in the different `customer` directories since they (most likely) have different deployment configuration.
   103  
   104      $ cat customer1/.buildtools
   105      CI=azure
   106      VCS=azure
   107      REGISTRY=dockerhub
   108      ORGANIZATION=com.organization
   109      DOCKERHUB_REPOSITORY=repository
   110      DOCKERHUB_USERNAME=user
   111      DOCKERHUB_PASSWORD=$(lpass show devenv/docker.com --password)
   112      AZURE_USER=user
   113      AZURE_TOKEN=token
   114      AZURE_ORG=organization
   115      AZURE_PROJECT=project
   116      PIPELINE_VARIABLES=(
   117      ["DOCKERHUB_REPOSITORY"]="repository"
   118      ["DOCKERHUB_USERNAME"]="user"
   119      ["DOCKERHUB_PASSWORD"]="secret:$(lpass show devenv/docker.com --password)"
   120      ["BUILDTOOLS_CONTENT"]="$(lpass show devenv/organization/team/buildtools --notes | base64 -w0)"
   121      ["KUBECONFIG_CONTENT"]="$(lpass show devenv/organization/team/kubeconfig --notes | base64 -w0)"
   122      )
   123      valid_environments=(
   124          ["local"]="--context docker-for-desktop --namespace default"
   125          ["staging"]="--context docker-for-desktop --namespace staging"
   126          ["prod"]="--context docker-for-desktop --namespace prod"
   127      )
   128  
   129  This defines three environments (local,staging,prod) all which are to be deployed to a local Kubernetes cluster but in different namespaces. 
   130  
   131      $ cat customer2/.buildtools
   132      valid_environments=(
   133          ["local"]="--context docker-for-desktop --namespace local"
   134          ["prod"]="--context kube-cluster-prod --namespace prod"
   135      )
   136  
   137  Context and namespaces must be provided/created/configured elsewhere.
   138  
   139  ### Configuration for service-setup
   140  The `service-setup` script need to know where to scaffold things (i.e. which VCS, CI and container registry to use and how to connect to them).
   141  The environment variables `CI`, `VCS` and `REGISTRY` are used to define this.
   142  Depending on the values of those variables, other variables are required as well. See each section below for the required variables.
   143  Values from the associative array `PIPELINE_VARIABLES` will be created as pipeline-variables in the CI-system. If the value is prepended vith `secret:` the variable will be a secret (if the CI-system supports that).
   144  
   145  #### Azure Devops
   146  If `CI` and/or `VCS` is set to `azure` the following variables are required:
   147  
   148  | Variable | Value |
   149  |----------|-------|
   150  | AZURE_USER | Azure username |
   151  | AZURE_TOKEN | Azure Personal Access Token |
   152  | AZURE_ORG | The organization name in Azure |
   153  | AZURE_PROJECT | The project name in Azure where repository and build-pipeline will be created |
   154  
   155  #### Buildkite
   156  If `CI` is set to `buildkite` the following variables are required:
   157  
   158  | Variable | Value |
   159  |----------|-------|
   160  | BUILDKITE_TOKEN | Buildkite Access Token |
   161  | BUILDKITE_ORG | The organization name in Buildkite where the build-pipeline will be created |
   162  
   163  #### GitlabCI
   164  If `CI` or `VCS` is set to `gitlab` the following variables are required:
   165  
   166  | Variable | Value |
   167  |----------|-------|
   168  | GITLAB_TOKEN | Gitlab Access Token |
   169  | GITLAB_GROUP | The group name in Gitlab where project will be created |
   170  
   171  ### Configuration using environment variables
   172  The `.buildtools` file can be created by defining an environment variable in the build pipeline named `BUILDTOOLS_CONTENT`. The value should be a base64-encoded string.
   173  On MacOS the value can be created and copied to the clipboard using the following snippet:
   174  
   175      cat - <<EOF | base64 -w0 | pbcopy
   176      valid_environments=(
   177          ["local"]="--context docker-for-desktop --namespace local"
   178          ["prod"]="--context kube-cluster-prod --namespace prod"
   179      )
   180      EOF
   181  
   182  The Kubernetes contexts to deploy to are configured by setting the `KUBECONFIG_CONTENT` variable. The value should be a base64-encoded string containing the Kubernetes config for the clusters you want to be able to deploy to.
   183  On MacOS the value can be created and copied to the clipboard using the following snippet:
   184  
   185      cat ~/.kube/config.d/prod-cluster.yaml | base64 -w0 | pbcopy
   186  
   187  The scripts assume that the project follow the directory layout described below.
   188  
   189  ## Project structure
   190  The project folder must be a [Git](https://git-scm.com/) repository, with a least one commit.
   191  
   192  There must be a `k8s` directory in the root of your project file. This directory contains all the `yaml` files used to describe the Kubernetes deployment tasks needed to run this service.
   193  Environment specific files can be handled in two different ways depending on personal preference. They can either be located in sub-directories, for example `k8s/local` for local setup.
   194  
   195      $ cd projecct
   196      $ tree
   197      .
   198      └── k8s
   199          ├── deploy.yaml
   200          ├── local
   201          │   ├── ingress.yaml
   202          │   └── setup.sh
   203          └── prod
   204              └── ingress.yaml
   205  
   206  Or they can be defined using a `-<environment>` suffix, i.e. ingress-prod.yaml
   207  
   208      $ cd projecct
   209      $ tree
   210      .
   211      └── k8s
   212          ├── deploy.yaml
   213          ├── ingress-local.yaml
   214          ├── ingress-prod.yaml
   215          └── setup-local.sh
   216  
   217  ## Running in a CI/CD environment
   218  The tools recognize which CI/CD environment they are executed in based on which environment variables are present.
   219  
   220  | Variable      | CI/CD environment     |
   221  | ------------- | --------------------- |
   222  | VSTS_PROCESS_LOOKUP_ID | Azure Devops |
   223  | BUILDKITE_COMMIT | Buildkite |
   224  | GITLAB_CI | GitlabCI |
   225  
   226  ## Support for different Docker container registries
   227  The container registry to use when running `docker:push` is also defined by environment variables.
   228  
   229  | Variable      | Container registry    | Example value |
   230  | ------------- | --------------------- | ------------- |
   231  | DOCKERHUB_REPOSITORY | Docker Hub | bitnami (resulting in bitnami/\<image> |
   232  | ECR_URL | AWS ECR | 12345678.dkr.ecr.eu-west-1.amazonaws.com |
   233  | CI_REGISTRY_IMAGE | Gitlab Registry | registry.gitlab.com/sparetimecoders/build-tools |
   234  | QUAY_REPOSITORY | Quay.io | quay.io/bitnami |
   235  
   236  
   237  Other environment variables that need to be defined (either automatically by the CI/CD environment or manually in the build pipeline) for each of the container registries are defined below.
   238  
   239  ### Docker Hub
   240  | Variable | Description |
   241  | -------- | ----------- |
   242  | DOCKERHUB_USERNAME | Username |
   243  | DOCKERHUB_PASSWORD | Password |
   244  
   245  ### AWS ECR
   246  | Variable | Description |
   247  | -------- | ----------- |
   248  | ECR_REGION | Optionally specified region, will use eu-west-1 as default value |
   249  
   250  ### Gitlab Registry
   251  | Variable | Description |
   252  | -------- | ----------- |
   253  | CI_BUILD_TOKEN | The build-token set by GitlabCI |
   254  | CI_REGISTRY | The URL to the registry set by GitlabCI |
   255  
   256  ### Quay.io
   257  | Variable | Description |
   258  | -------- | ----------- |
   259  | QUAY_USERNAME | Username |
   260  | QUAY_PASSWORD | Password |
   261  
   262  ## Example Azure Devops pipeline (azure-pipelines.yml)
   263  
   264      resources:
   265        containers:
   266        - container: build-tools
   267          image: registry.gitlab.com/sparetimecoders/build-tools:master
   268      
   269      jobs:
   270      - job: build_and_deploy
   271        pool:
   272          vmImage: 'Ubuntu 16.04'
   273        container: build-tools
   274        steps:
   275        - script: |
   276            build
   277            push
   278          name: build
   279          env:
   280            DOCKERHUB_PASSWORD: $(DOCKERHUB_PASSWORD)
   281            QUAY_PASSWORD: $(QUAY_PASSWORD)
   282        - script: deploy staging
   283          name: deploy_staging
   284          condition: succeeded()
   285  
   286  ## Example Buildkite pipeline (.buildkite/pipeline.yml)
   287  
   288      steps:
   289        - command: |-
   290            build
   291            push
   292          label: build
   293      
   294        - wait
   295      
   296        - command: |-
   297            ${BUILD_TOOLS_PATH}/deploy staging
   298          label: Deploy to staging
   299          branches: "master"
   300      
   301        - block: ":rocket: Release PROD"
   302          branches: "master"
   303      
   304        - command: |-
   305            ${BUILD_TOOLS_PATH}/deploy prod
   306          label: Deploy PROD
   307          branches: "master"
   308      
   309  ## Example GitlabCI pipeline (.gitlab-ci.yaml)
   310  
   311      stages:
   312        - build
   313        - deploy-staging
   314        - deploy-prod
   315      
   316      variables:
   317        DOCKER_HOST: tcp://docker:2375/
   318      
   319      image: registry.gitlab.com/sparetimecoders/build-tools:master
   320      
   321      build:
   322        stage: build
   323        services:
   324          - docker:dind
   325        script:
   326        - build
   327        - push
   328      
   329      deploy-to-staging:
   330        stage: deploy-staging
   331        when: on_success
   332        script:
   333          - echo Deploy to staging.
   334          - deploy staging
   335        environment:
   336          name: staging
   337      
   338      deploy-to-prod:
   339        stage: deploy-prod
   340        when: on_success
   341        script:
   342          - echo Deploy to PROD.
   343          - deploy prod
   344        environment:
   345          name: prod
   346        only:
   347          - master
   348  
   349  # Developing
   350  
   351  ## Generate test mocks
   352      mockgen -package=mocks -destination=pkg/config/mocks/MockRepositoriesService.go gitlab.com/sparetimecoders/build-tools/pkg/config RepositoriesService