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