diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 85523c0..d3d78d0 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -28,7 +28,9 @@ jobs: # Run yamllint to lint YAML - name: Lint YAML files - run: yamllint --no-warnings ./ + run: | + yamllint --no-warnings \ + ./ # Run shellcheck to lint shell scripts - name: Lint shell scripts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c8d9ae9..8e9e785 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,107 +1,107 @@ -name: Create a release - -# Use this workflow to: -# - Create a release from a branch -# - Update major and minor tags when a release is published +name: Create a draft release on: # Run when manually triggered workflow_dispatch: inputs: - # User inputs the release version, for example `2.2.1` version: - description: 'Release version to create, for example 2.2.1' + description: 'Release version to create, for example 2.3.0' required: true - default: "2.2.1" - # Run when a release is published - release: - types: [published] + default: "2.3.0" + # Run when a release branch is pushed + push: + branches: + - 'release-*.*.*' defaults: run: shell: bash -env: - GIT_AUTHOR_NAME: ${{ github.repository_owner }} - GIT_AUTHOR_EMAIL: ${{ github.repository_owner }}@users.noreply.github.com - jobs: - create-release: - if: ${{ github.event_name == 'workflow_dispatch' }} + + meta: + name: Parse event data into outputs runs-on: ubuntu-20.04 outputs: - changelog: ${{ steps.changelog.outputs.changelog }} + ver: ${{ steps.get-ver.outputs.ver }} + tag: ${{ steps.get-tag.outputs.tag }} + branch: ${{ steps.get-ref.outputs.branch }} + ref: ${{ steps.get-ref.outputs.ref }} steps: - # Check out this repository at the same ref that triggered - # this workflow run - - uses: actions/checkout@v2 - - # Ensure the specified version has a section in CHANGELOG.md - - name: Check CHANGELOG.md for '${{ github.event.inputs.version }}' - id: changelog + - name: Checkout ${{ github.repository }}:${{ github.ref }} + uses: actions/checkout@v2 + - name: 'ver: Version number for this release' + id: get-ver run: | - _ver="${{ github.event.inputs.version }}" - _changelog= - if grep -Fq "## [${_ver}]" docs/CHANGELOG.md; then - echo "Found '## [${_ver}]' in CHANGELOG.md :+1:" - else - echo "FAIL: Did not find '## [${_ver}]' in CHANGELOG.md" - exit 1 - fi - # TODO: Make this :point_down: actually work - _changelog=":shrug:" - echo "Set changelog to '${_changelog}'." - echo "::set-output name=changelog::${_changelog}" + case "${{ github.event_name }}" in + "workflow_dispatch") + _ver="${{ github.event.inputs.version }}" ;; + "push") + _ver="${GITHUB_REF#refs/heads/release-}}" ;; + *) + echo "FAIL: Unexpected workflow trigger." + exit 1 + esac + echo "::set-output name=ver::${_ver}" + - name: 'tag: Tag for this release' + id: get-tag + run: | + _tag="v${{ steps.get-ver.outputs.ver }}" + echo "::set-output name=tag::${_tag}" + - name: 'branch, ref: Branch for this release' + id: get-ref + run: | + _branch="release-${{ steps.get-ver.outputs.ver }}" + _ref="refs/heads/${_branch}" + echo "::set-output name=branch::${_branch}" + echo "::set-output name=ref::${_ref}" - # Create the draft release - # https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#get-a-release - # https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#create-a-release - # https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#get-the-latest-release + create-branch: + name: Create the release branch for ${{ needs.meta.outputs.ver }} + needs: meta + if: ${{ github.ref != needs.meta.outputs.ref }} + runs-on: ubuntu-20.04 + steps: + - name: Checkout ${{ github.repository }}:${{ github.ref }} + uses: actions/checkout@v2 + - name: Configure Git client + run: | + _user="${{ github.repository_owner }}" + _email="${_user}@users.noreply.github.com" + git config user.name "${_user}" + git config user.email "${_email}" + - name: Create branch ${{ needs.meta.outputs.branch }} + run: | + _ghref="${{ github.ref }}" + _myref="${{ needs.meta.outputs.ref }}" + git update-ref "${_myref}" "${_ghref}" + git push origin "${_myref}" - - name: Create the draft release - id: mkrel + create-release: + name: Create draft release ${{ needs.meta.outputs.tag }} + needs: [meta, create-branch] + environment: uses-pat + runs-on: ubuntu-20.04 + steps: + - name: Checkout ${{ github.repository }}:${{ github.ref }} + uses: actions/checkout@v2 + - name: Assemble data payload for releases API call + id: get-data run: | - _ver="${{ github.event.inputs.version }}" - _tag="v${_ver}" _repo="${{ github.repository }}" - _relbranch="${GITHUB_REF#refs/heads/}" - echo "${_ver} ${_tag} ${_repo} ${_relbranch}" - _data="{ \"tag_name\": \"${_tag}\", - \"target_commitish\": \"${_relbranch}\", - \"name\": \"${_repo#*/} ${_tag}\", - \"body\": \"words words words\", - \"draft\": true }" - echo "${_data}" - # Create the draft release + _tag="${{ needs.meta.outputs.tag }}" + _branch="${{ needs.meta.outputs.branch }}" + _body="words words words" + _draft="true" + _data="{ \"tag_name\": \"${_tag}\", \ + \"target_commitish\": \"${_branch}\", \ + \"name\": \"${_repo#*/} ${_tag}\", \ + \"body\": \"${_body}\", \ + \"draft\": ${_draft} }" + echo "::set-output name=data::${_data}" + - name: Call releases API to create draft release + run: | + _data='${{ steps.get-data.outputs.data }}' echo "${_data}" | \ GITHUB_TOKEN=${{ secrets.PAT }} \ gh api -X POST /repos/:owner/:repo/releases --input - - - # When a release is published, update short - # version tags, for example v2 and v2.2 - update-tags: - if: ${{ github.event_name == 'release' }} - runs-on: ubuntu-20.04 - steps: - # Check out this repository at the same ref that triggered - # this workflow run - - uses: actions/checkout@v2 - - # Update short version tags, for example v2 and v2.2 - - name: Update major and minor version tags - id: roll-tags - run: | - # Set up variables. - TAG="${INPUT_TAG:-${GITHUB_REF#refs/tags/}}" # v2.2.0 - MINOR="${TAG%.*}" # v2.2 - MAJOR="${MINOR%.*}" # v2 - MESSAGE="Release ${TAG}" - # Set up Git. - git config user.name "${GIT_AUTHOR_NAME}" - git config user.email "${GIT_AUTHOR_EMAIL}" - # Update MAJOR/MINOR tag - git tag -fa "${MAJOR}" -m "${MESSAGE}" - git tag -fa "${MINOR}" -m "${MESSAGE}" - # Push MAJOR/MINOR tag - git push --force origin "${MINOR}" - git push --force origin "${MAJOR}" diff --git a/.github/workflows/update-major.yml b/.github/workflows/update-major.yml new file mode 100644 index 0000000..76256f5 --- /dev/null +++ b/.github/workflows/update-major.yml @@ -0,0 +1,50 @@ +name: Update major tag + +on: + # Run when a release tag is pushed + push: + branches-ignore: + - '**' + tags: + - 'v*.*.*' + +permissions: + contents: write + +jobs: + # When a release tag is pushed, update the matching short + # version tag, for example v2 + update-tags: + runs-on: ubuntu-20.04 + steps: + + # Check out this repository at the same ref that triggered + # this workflow run + - uses: actions/checkout@v2 + + - name: Configure Git client + run: | + _user="${{ github.repository_owner }}" + _email="${_user}@users.noreply.github.com" + git config user.name "${_user}" + git config user.email "${_email}" + + # Update short version tag, for example v2 + - name: Update major version tag + id: roll-tag + run: | + # Set up variables. + _tag="${INPUT_TAG:-${GITHUB_REF#refs/tags/}}" # v2.2.0 + _major="${MINOR%.*}" # v2 + _msg="Release ${_tag}" + _curr="$(gh api /repos/:owner/:repo/releases/latest | \ + jq -r .tag_name)" + # If tag pushed is not for latest release, exit early + if [ "$_tag" != "$_curr" ]; then + echo "SKIP: Tag pushed ($_tag) is not for latest release." + exit 0 + fi + # Update _major tag + git tag -fa "${_major}" -m "${_msg}" + # Push _major tag + git push --force origin "${_major}" diff --git a/Makefile b/Makefile index 06284e4..0bc2f17 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,8 @@ lint-yaml: @docker run --rm \ -v "$(realpath .)":"/tmp/lint":ro \ --entrypoint /usr/local/bin/yamllint \ - github/super-linter --no-warnings /tmp/lint + github/super-linter --no-warnings \ + /tmp/lint @echo "All the YAML things linted!" lint-shell: diff --git a/docs/release.md b/docs/release.md index 464b187..1253c6c 100644 --- a/docs/release.md +++ b/docs/release.md @@ -1,24 +1,26 @@ # Release checklist -TODO: Make this simpler and more reliable. +- [ ] Is the [changelog] up-to-date? -## Prerequisites -- [ ] Identify the release version, for example `2.2.1` -- [ ] Create a corresponding branch from `main`, for example `release-2.2.1` +- [ ] Pick the release version, for example `2.3.0` +- [ ] Create a matching branch from `main`, for example `release-2.3.0` - [ ] Push your branch +- [ ] Did the _Create a draft release_ [workflow] run automatically? -## Run [the _Create a release_ workflow](https://github.com/solvaholic/octodns-sync/actions) from your branch -Which will perform these tasks: +- [ ] Rename _Unreleased_ section of CHANGELOG.md to release version +- [ ] Any other changes to make? -- [ ] Ensure the specified version has a section in CHANGELOG.md -- [ ] Create the draft release -## Finalize and publish [the release](https://github.com/solvaholic/octodns-sync/releases) +- [ ] Finalize and publish the [release], which pushes the release tag +- [ ] Did the _Update major tag_ [workflow] run automatically? -Which will push the release tag. If you'd like to publish this release to the marketplace, be sure to check that box. -## Clean up +- [ ] Delete any [branches] you're done with -- [ ] Delete any [branches](https://github.com/solvaholic/octodns-sync/branches) you're done with + +[changelog]: https://github.com/solvaholic/octodns-sync/blob/main/docs/CHANGELOG.md +[workflow]: https://github.com/solvaholic/octodns-sync/actions +[release]: https://github.com/solvaholic/octodns-sync/releases +[branches]: https://github.com/solvaholic/octodns-sync/branches \ No newline at end of file