Skip to content

๐Ÿงช Release Version

Release

As streams of changes make it into the production branch and are versioned in batches, an essential part of continuous delivery/deployment is to produce artifacts from versions which can then be deployed to various targets.

Releases are deployable software iterations you can package and make available for a wider audience to download and use.

How do we determine when to create a release? Let's see...

Show milestone package delivery artifacts


Exercise: Create a Release of Versions

As you can guess already, GitHub provides an event that encapsulates the activity of creating a tag and pushing it to a repository. We will automate addressing such events, so that we can create a release when necessary.


Implement Release Creation

In the file explorer, create a new workflow .github/workflows/continuous.delivery.yml as follows.

.github/workflows/continuous.delivery.yml
name: Package Delivery Artifacts & Create Release

on:
  push:
    tags:
      - "*-release"

permissions:
  contents: write

env:
  CI: true
  SITE_DIR: site

jobs:
  package-delivery:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - uses: actions/setup-python@v4
        with:
          python-version: 3.12
      - name: Install Python dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
      - name: Build Site
        run: |
          python -m mkdocs build --clean --strict --verbose --site-dir '${{ env.SITE_DIR }}'
      - name: Archive Site
        run: |
          zip -r ${{ env.SITE_DIR }}.zip ${{ env.SITE_DIR }}
      - run: |
          echo "Site directory ${{ env.SITE_DIR }} content:"
          ls -al ${{ env.SITE_DIR }}

      - uses: actions/create-github-app-token@v1
        id: generate-app-token
        with:
          app-id: ${{ vars.APP_ID_ACTIONS_ASSISTANT }}
          private-key: ${{ secrets.APP_PRIVATE_KEY_ACTIONS_ASSISTANT }}

      - name: Draft release
        uses: actions/github-script@v6
        id: draft-release
        with:
          github-token: ${{ steps.generate-app-token.outputs.token }}
          script: |

            const response = await github.request(
              'POST /repos/{owner}/{repo}/releases',
              {
                owner: context.repo.owner,
                repo: context.repo.repo,
                draft: true,
                tag_name: '${{ github.ref }}',
                discussion_category_name: 'announcements',
                generate_release_notes: true,
                make_latest: 'legacy',
                headers: {
                  'X-GitHub-Api-Version': '2022-11-28'
                }
              }
            );

            console.dir(response);

            return response.data.id;

      - name: Upload release asset
        run: |
          curl -L \
            -X POST \
            -H "Accept: application/vnd.github+json" \
            -H "Authorization: Bearer ${{ steps.generate-app-token.outputs.token }}" \
            -H "X-GitHub-Api-Version: 2022-11-28" \
            -H "Content-Type: application/octet-stream" \
            "https://uploads.github.com/repos/${{ github.repository }}/releases/${{ steps.draft-release.outputs.result }}/assets?name=${{ env.SITE_DIR }}.zip" \
            --data-binary "@${{ env.SITE_DIR }}.zip"

      - name: Publish release
        uses: actions/github-script@v6
        id: publish-release
        with:
          github-token: ${{ steps.generate-app-token.outputs.token }}
          script: |

            const response = await github.request(
              'PATCH /repos/{owner}/{repo}/releases/{release_id}',
              {
                owner: context.repo.owner,
                repo: context.repo.repo,
                release_id: ${{ steps.draft-release.outputs.result }},
                draft: false,
                discussion_category_name: 'announcements',
                make_latest: 'true',
                headers: {
                  'X-GitHub-Api-Version': '2022-11-28'
                }
              }
            );

            console.dir(response);

Analysis

  • Lines 3 - 6

    The release creation workflow will be triggered by tag pushes and when the pushed tag version is suffixed with the -release metadata.

  • Lines 29 - 34

    In the two steps included here, the site is built and archived as a release artifact.

  • Lines 39 - 43

    A GitHub App will be used as the actor for the operations we shall be executing. Hence the actions/create-github-app-token@v1 action is used here to generate an authorization token for the app.

    What is a GitHub App?

    GitHub Apps, much like service accounts and bots, are tools that extend GitHub's functionality. You can build a GitHub App to provide flexibility and reduce friction in your processes, without needing to sign in a user or create a service account . GitHub Apps can do things on GitHub like open issues, comment on pull requests, and manage projects. They can also do things outside of GitHub based on events that happen on GitHub. For example, a GitHub App can post on Slack when an issue is opened on GitHub.

    When you use the repository's GITHUB_TOKEN to perform tasks, events triggered by the GITHUB_TOKEN, with the exception of workflow_dispatch and repository_dispatch, will not create a new workflow run. This prevents you from accidentally creating recursive workflow runs. For example, if a workflow run pushes code using the repository's GITHUB_TOKEN, a new workflow will not run even when the repository contains a workflow configured to run when push events occur.

    ~ Using the GITHUB_TOKEN in a workflow

    So, we are authorizing operations as a GitHub App to enable the execution of the operation to further trigger other workflow flow runs, possibly.

  • Lines 45 - 70

    A draft release is created by the respective step, allowing for modification of the release before publishing it. The release references the tag that had triggered the workflow.

  • Lines 72 - 81

    This step leverages GitHub's ReST API to adjust the previously created draft release, specifically adding the archive created in the Archive Site step to the release as an asset.

  • Lines 83 - 105

    Having drafted the release and attached deployable assets to it, the Publish release step ultimately publishes the release by flipping the state of it draft attribute to false.


Commit and publish your changes

You can link your changes to an issue

Recall the issue you created earlier and its respective issue number, you will use it to link your current changes to the issue.

1
2
3
git add .
git commit -m "$(printf 'Create a tetris game to drive site engagement\n\n-Implement release automation\n\n- Resolves #<ISSUE-NUMBER>')"
git push origin feature/tetris-game

๐Ÿ“š Resources