Skip to content

Commit

Permalink
feat: add version tagging (#4)
Browse files Browse the repository at this point in the history
* add tagging.sh

* filter tags that match semver regex

* fetch tags in tagging.sh

* handle first release tag

* handle first release tag

* tagging.sh add create tag for devops or github

* add tagging pipeline samples

* add documentation

* add version-tagging doc

* update docs, add release-please to repo

* update version tagging doc

* fix: pin pipeline runner to ubuntu-22.04
  • Loading branch information
alaincormier-ssc authored Feb 3, 2023
1 parent 1f630d6 commit f944469
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 18 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/release-please.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
on:
push:
branches:
- main
name: release-please

# add minimum permissions
permissions:
contents: write
pull-requests: write

jobs:
release-please:
runs-on: ubuntu-22.04
steps:
- uses: google-github-actions/release-please-action@v3
with:
command: manifest
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "0.0.1"
}
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Introduction
This is a repo to store common scripts, pipeline templates, etc.
This is a repo to centrally store common scripts, pipeline samples, etc.

It's designed to be used as a git submodule.
It's designed to be used as a git submodule in [deployment repos](https://github.com/ssc-spc-ccoe-cei/gcp-repo-template) and should be pinned to a specific version tag or commit SHA.
10 changes: 0 additions & 10 deletions azure-pipelines/TODO

This file was deleted.

6 changes: 0 additions & 6 deletions azure-pipelines/templates/sample.yaml

This file was deleted.

14 changes: 14 additions & 0 deletions pipeline-samples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Pipeline Samples

This folder contains samples of YAML definitions primarily for Azure DevOps Pipelines (`.azure-pipelines` directory). In some cases, the equivalent GitHub Actions (`.github` directory) may also be available.

## Adding / Editing a Pipeline

Simply copy a sample YAML file to your repo in the appropriate directory (`.azure-pipelines` or `.github/workflows`).

Each sample may have instructions specific to itself.

For general documentation on how to manage pipelines, please refer to the [gcp-documentation](https://github.com/ssc-spc-ccoe-cei/gcp-documentation/blob/main/Architecture/Pipelines.md) repo.

> **!!! Note when changing the `tools` sub module version !!!**<br>
Because the pipeline samples can have dependencies in the `scripts\` directory, it's important to compare with your copy if a change is required.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# A simple pipeline to increment version tags for a git repo

# can be set to false to disable the check for an entry in CHANGELOG.md
variables:
VALIDATE_CHANGELOG: 'true'

# a "Build Validation Policy" (PR trigger) must also be created
trigger:
- main

pool:
vmImage: ubuntu-22.04

jobs:
- job: version_tagging
steps:
- checkout: self
persistCredentials: true

- script: |
echo "Checking out git submodule with 'bash modupdate.sh' ..."
bash modupdate.sh
displayName: 'Checkout git submodule'
- script: |
echo "Running 'bash tools/scripts/cicd/version-tagging.sh' ..."
bash tools/scripts/cicd/version-tagging.sh
displayName: 'Validate git tag - create it on push to main trigger'
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# A simple pipeline to increment version tags for a git repo
name: version_tagging

# can be set to false to disable the check for an entry in CHANGELOG.md
env:
VALIDATE_CHANGELOG: 'true'

# Triggers the workflow on push or pull request events but only for the "main" branch
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
# This workflow contains a single job called "version_tagging" and needs write permission
version_tagging:
permissions:
contents: write

runs-on: ubuntu-22.04

steps:
- uses: actions/checkout@v3

- name: Checkout git submodule
run: |
echo "Checking out git submodule with 'bash modupdate.sh' ..."
bash modupdate.sh
- name: Validate git tag - create it on push to main trigger
run: |
echo "Running 'bash tools/scripts/cicd/version-tagging.sh' ..."
bash tools/scripts/cicd/version-tagging.sh
12 changes: 12 additions & 0 deletions pipeline-samples/version-tagging/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Changelog

All notable changes to this repo will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.0] - YYYY-MM-DD

### Initial

- fix for a sample issue
36 changes: 36 additions & 0 deletions pipeline-samples/version-tagging/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Version Tagging
A sample for a custom (basic) way to manage git tags and a change log.

The pipeline follows [semantic versioning](https://semver.org/) (MAJOR.MINOR.PATCH).

> **It does NOT support a "v" prefix.**
1. Copy the sample `version-tagging.yaml` in the proper pipeline folder of your repo.
1. Copy the sample `VERSION.txt` and `CHANGELOG.md`* in the root of your repo.
1. Add the pipeline.

**If a changelog is not required, `VALIDATE_CHANGELOG` can be set to 'false' in `version-tagging.yaml`.*

## Requirements
- `tools` sub module.
- `VERSION.txt` in repo root.
- `CHANGELOG.md` in repo root, if a change log is required.
- If using Azure DevOps:
- "Create tag" permission on repo for user "{project} Build Service ({organization})". This may be enabled by default depending on security settings.
- "Contribute" permission on repo for user "{project} Build Service ({organization})". This may only be required for the creation of the first tag depending on your environment.
- A "Build Validation Policy" (PR trigger).
- If using GitHub:
- "contents" write permission on repo for GitHub Actions. This may be enabled by default depending on security settings.

## Dependencies
- `tools/scripts/cicd/version-tagging.sh`

## Usage

Before creating a PR, push these changes as well:
- Edit `VERSION.txt` to increment the version accordingly. (Reminder: no "v" prefix allowed.)
- Edit `CHANGELOG.md` to add an entry for the new version. It must be enclosed in square brackets, for example [0.0.0]. Refer to the sample file for more info.

The PR trigger will run the pipeline to validate the new version tag. No tag will be created.

When the PR is merged in the main branch, the pipeline will run again to re-validate and create the tag.
1 change: 1 addition & 0 deletions pipeline-samples/version-tagging/VERSION.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.0.0
12 changes: 12 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"packages": {
".": {
"changelog-path": "CHANGELOG.md",
"prerelease": true
}
},
"bootstrap-sha": "b8755590f1c4a3979ef502fd686547bd49cc0a42",
"release-type": "simple",
"bump-minor-pre-major": true,
"include-v-in-tag": false
}
103 changes: 103 additions & 0 deletions scripts/cicd/version-tagging.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#!/bin/bash

# this script is called from pipelines to validate a proper semantic version on the first line of 'VERSION.txt'
# it does NOT support a 'v' prefix (v0.0.0)
# it optionally checks that an entry is included in 'CHANGELOG.md'

# PowerShell's built-in [semver] type is used to perform a greater than operation
# a bash equivalent function would need to be created if PowerShell is not available

# Bash safeties: exit on error, pipelines can't hide errors
set -eo pipefail

# get the directory of this script and source print-colors.sh for better readability of the script's outputs
SCRIPT_ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "${SCRIPT_ROOT}/../common/print-colors.sh"

releaseVersion="$(head -1 VERSION.txt)"

##########
# validate tag syntax
print_info "Validating semantic version syntax in VERSION.txt ..."
SEMVER_PATTERN='^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
# use perl-regexp for compatibility with '\d'
if echo "${releaseVersion}" | grep --perl-regexp --quiet ${SEMVER_PATTERN} ; then
print_success "'$releaseVersion' is a valid semantic release version number."
else
print_error "'$releaseVersion' is not a valid semantic release version number. \n \
refer to https://semver.org/ for valid pattern, using the 2nd regular expression at the bottom of the page."
exit 1
fi

##########
# validate no tag duplication
print_info "Checking if the git tag already exists for release version ..."
# the expected return code if the tag doesn't exit is 2
# save non-zero exit codes in a temporary variable to avoid the entire script from failing
rc=0
git ls-remote --tags --exit-code origin "refs/tags/${releaseVersion}" || rc=$?
if [[ $rc -eq 2 ]] ; then
print_success "'$releaseVersion' git tag does not exist."
else
print_error "'$releaseVersion' git tag already exists or repo could not be reached. \n \
Please check and update VERSION.txt"
exit 1
fi

##########
# validate tag increment
print_info "Checking if the release version is newer than the latest existing tag version ..."
git fetch --tags --recurse-submodules=no --quiet

# ensure a properly formatted tag exists before performing comparison
if git tag | grep --perl-regexp --quiet ${SEMVER_PATTERN} ; then

# using powershell's built-in [semver] type to perform the greater than operation
# save non-zero exit codes in a temporary variable to avoid the entire script from failing
currentLatestVersion="$(git tag | grep --perl-regexp ${SEMVER_PATTERN} | sort --reverse --version-sort | head -1)"
rc=0
pwsh -Command "if (-not ([semver]\"$releaseVersion\" -gt [semver]\"$currentLatestVersion\") ) {exit 1}" || rc=$?
if [[ $rc -eq 0 ]] ; then
print_success "'$releaseVersion' is greater than latest existing tag '$currentLatestVersion'."
else
print_error "'$releaseVersion' is not greater than latest existing tag '$currentLatestVersion'."
exit 1
fi
else
print_success "'$releaseVersion' will be the first release version. A properly formatted tag does not currently exist."
fi

##########
# validate changelog, unless the 'VALIDATE_CHANGELOG' env. variable is set to false
if [[ "${VALIDATE_CHANGELOG}" != "false" ]] ; then
print_info "Checking if release version is referenced in CHANGELOG.md ..."

if grep --fixed-strings --quiet "[${releaseVersion}]" CHANGELOG.md ; then
print_success "'[$releaseVersion]' is included in CHANGELOG.md."
else
print_error "'[$releaseVersion]' is not found in CHANGELOG.md. \n \
Please make sure the CHANGELOG.md is updated with the released changes."
exit 1
fi
fi

##########
# validate when tag is created
print_info "Checking if the tag should be created (when pipeline is running through CI on push to main trigger) ..."

# Azure DevOps and GitHub runners have environment variables to check specific run conditions
# a tag should not be created if it runs from a PR or if it runs manually

if [[ "${BUILD_SOURCEBRANCHNAME}" == "main" ]] && [[ "${BUILD_REASON}" == "IndividualCI" || "${BUILD_REASON}" == "BatchedCI" ]] ; then
echo -e "Creating and pushing tag to Azure DevOps repo ...\n"
git tag ${releaseVersion}
git push origin tag ${releaseVersion}

elif [[ "${GITHUB_REF_NAME}" == "main" && "${GITHUB_EVENT_NAME}" == "push" ]] ; then
echo -e "Creating and pushing tag to GitHub repo ...\n"
git tag ${releaseVersion}
git push origin tag ${releaseVersion}

else
echo -e "A tag will not be created yet. The pipeline is either running from a PR or manually.\n"
fi

0 comments on commit f944469

Please sign in to comment.