|
| 1 | +# gitlab-semantic-versioning |
| 2 | + |
| 3 | +Docker image that can be used to automatically version projects using semantic versioning. |
| 4 | + |
| 5 | +Visit [semver.org](https://semver.org/) to read more about semantic versioning. |
| 6 | + |
| 7 | +## How is the version determined? |
| 8 | + |
| 9 | +Versions are being maintained using git tags. |
| 10 | + |
| 11 | +If no git tag is available, the first version update will result in version 1.0.0. |
| 12 | +If git tags are available, it will determine whether to do a major, minor, or patch update based on specific merge request labels. The `bump-minor` and `bump-major` labels exist to do either a minor or major bump. If a merge request has no labels attached, it will perform a patch update by default. |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +### Group labels |
| 17 | + |
| 18 | +As stated above, the version update workflow relies on merge request labels to determine the new version. The `bump-minor` and `bump-major` labels have been set as global GitLab labels. However, global labels only propogate to groups created after setting a global label. When adding a global label, they [do not automatically propogate to existing groups](https://gitlab.com/gitlab-org/gitlab-ce/issues/12707). |
| 19 | + |
| 20 | +If you cannot select the specified labels in your merge request, your group was most likely created before the global labels were defined. Please follow [this guide to setup group-specific labels](https://docs.gitlab.com/ee/user/project/labels.html) |
| 21 | + |
| 22 | +### API token and group |
| 23 | + |
| 24 | +To extract the labels from merge requests, we need an API token to access the Gitlab API. Unfortunately, [GitLab doesn't yet support non-user specific access tokens](https://gitlab.com/gitlab-org/gitlab-ee/issues/756). |
| 25 | + |
| 26 | +Ask your GitLab administrator to add a dummy user `${group_name}_npa` to GitLab with access only to your project group. Log in with this user, and create a [personal access token](https://gitlab.wbaa.pl.ing.net/profile/personal_access_tokens) with api scope access. |
| 27 | + |
| 28 | +Copy the generated API token and keep it available for the next section. |
| 29 | + |
| 30 | +### Group-level variables |
| 31 | + |
| 32 | +The NPA username and token need to be injected into the version-update container as environment variables. For this, we'll use group-level variables. |
| 33 | + |
| 34 | +Go to your group's variables section under `Settings` -> `CI / CD`. |
| 35 | + |
| 36 | +Add the following variables: |
| 37 | + |
| 38 | +| Key | Value | |
| 39 | +|-----------------|----------------------------------------------------------------------| |
| 40 | +| NPA_USERNAME | The name of the NPA user created for your group: `${group_name}_npa` | |
| 41 | +| NPA_PASSWORD | The personal access token with API scope generated for the NPA user | |
| 42 | + |
| 43 | +## Pipeline configuration |
| 44 | + |
| 45 | +The pipeline configuration below will: |
| 46 | +1. Generate a unique version tag based on git describe |
| 47 | +2. Update the version for every build on the `master` branch. |
| 48 | +3. Tag the docker image built with the updated version as `latest` only for `tag` builds. |
| 49 | + |
| 50 | +This pipeline omits steps for building the project and pushing the resulting Docker image to the registry. |
| 51 | + |
| 52 | +``` |
| 53 | +stages: |
| 54 | + - generate-env-vars |
| 55 | + - version |
| 56 | + - tag-latest |
| 57 | +
|
| 58 | +variables: |
| 59 | + IMAGE_NAME: $CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME |
| 60 | +
|
| 61 | +generate-env-vars: |
| 62 | + stage: generate-env-vars |
| 63 | + script: |
| 64 | + - TAG=$(git describe --tags --always) |
| 65 | + - echo "export TAG=$TAG" > .variables |
| 66 | + - echo "export IMAGE=$IMAGE_NAME:$TAG" >> .variables |
| 67 | + - cat .variables |
| 68 | + artifacts: |
| 69 | + paths: |
| 70 | + - .variables |
| 71 | +
|
| 72 | +version: |
| 73 | + stage: version |
| 74 | + image: mrooding/gitlab-semantic-versioning:1.0.0 |
| 75 | + script: |
| 76 | + - python3 /version-update/version-update.py |
| 77 | + only: |
| 78 | + - master |
| 79 | +
|
| 80 | +tag-latest: |
| 81 | + stage: tag-latest |
| 82 | + image: docker:18.06.1-ce |
| 83 | + before_script: |
| 84 | + - source .variables |
| 85 | + script: |
| 86 | + - docker pull $IMAGE |
| 87 | + - docker tag $IMAGE $IMAGE_NAME:latest |
| 88 | + - docker push $IMAGE_NAME:latest |
| 89 | + only: |
| 90 | + - tag |
| 91 | +``` |
| 92 | + |
| 93 | +## Merge request instructions |
| 94 | + |
| 95 | +### Squash commits when merge request is accepted |
| 96 | + |
| 97 | +The new version will be determined based on the commit message. GitLab will automatically format a merge request commit message if the 'Squash commits when merge request is accepted` checkbox is checked during merge request creation. |
| 98 | + |
| 99 | +This workflow relies on that commit message format and will fail the pipeline if it cannot extract the merge request id from the commit message. |
| 100 | + |
| 101 | +Unfortunately, GitLab [doesn't yet allow for setting the checkbox to checked by default](https://gitlab.com/gitlab-org/gitlab-ce/issues/27956). Until implemented, make sure to manually check the squash option upon creation. |
| 102 | + |
| 103 | +### Add a label to indicate a minor or major update |
| 104 | + |
| 105 | +As described above, if you want to perform a minor or major update, don't forget to add the appropriate label to your merge request. |
0 commit comments