Build and Release are two distinct actions. Build should happen on each push in a feature branch
for early feedback about code quality (lint, tests). Once code is merged into main branch there should be Build (again!) and Release.
There are two ways how you can organize your workflows:
- (simple) you have one workflow with two jobs: Build and Release.
Build is run all the time, and a Release job is conditioned to run only on
mainbranch - (advanced) you have two workflows: Build and Release. Build workflow is called on every push in non-main branches,
and also it can be called from another workflow (
on: workflow_call:). Release workflow is called only on push in themainbranch, and inside it calls Build workflow Advanced setup is used when there are multiple types of releases: besides normal (when feature is merged intomainbranch) there are dev-release and "fixed version" when a version is passed explicitly as workflow argument:
/- normal release
build -- dev release
\- fixed version release
- (Docker specific) GitHub uses two actions:
actions/upload-artifactandactions/download-artifactto pass files between jobs. If you placedocker buildcommand in Build job - you can't access it in Release. So the only way is to placedocker buildin a Release job. Finally, if you have multiple release options, you end up with a workflow layout like this example:
/- normal release
build -- release -- dev release
\- fixed version release
Below is an example of advanced setup (two workflows):
build.yml
name: Build
on:
push:
branches-ignore:
- main
workflow_call: # Allow to call this workflow from Release workflow
inputs:
artifacts:
required: false
type: boolean
default: false
description: upload artifacts or not
jobs:
Build:
runs-on: ubuntu-latest
permissions:
contents: read # required for checkout
id-token: write # not always required, only if at some step you assume AWS role via OIDC
steps:
- name: Checkout code
uses: actions/checkout@v7
# Setup tools
# Install dependencies
# Run linting and tests
# Build/Package the artifact(s)
- name: Upload artifacts
if: inputs.artifacts # no point in uploading artifacts on every push in a feature branch
uses: actions/upload-artifact@v7
with: # configure what to uploadrelease.yml
name: Release
on:
push:
branches:
- main
jobs:
Build:
uses: ./.github/workflows/build.yml
with:
artifacts: true # for release purposes we want artifacts
secrets: inherit
permissions: # specify same permissions as in Build workflow
contents: read
id-token: write
Release:
needs: Build
runs-on: ubuntu-latest
environment: release # holds the `GH_TOKEN` secret, available only for `main` branch
permissions:
contents: read # required for checkout
id-token: write # not always required, only if at some step you assume AWS role via OIDC
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Download artifacts
uses: actions/download-artifact@v8
with:
path: # where to download artifact(s)
- name: Release
uses: agilecustoms/release@v6
with: # parameters specific to artifact type(s) being released
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }} # required to push commit and tagsIn many examples you may some inputs repeat, such as aws-account, aws-region, aws-role.
You can reduce code repetition by creating your own wrapper around agilecustoms/release.
For this just create a new GH repo with single file action.yml, see example gha-release.
Here you provide company-specific defaults, see comment # company-specific defaults.
For parameters that may vary - you add them in inputs section and pass them through, see comment # pass through inputs.
For pass-through inputs you can use either same defaults as in agilecustoms/release (like floating-tags default is true)
and for others you may want to set your own defaults (like summary).
Especially useful to provide default value for input release-plugins.
This is the recommended way to have shared release configuration among multiple repos.
Alternative is to have .releaserc.json file in each repo, but then you need to maintain it in multiple places.
See configuration for more details on configuration options.
Security note. In "dev-release" mode the aws-role is set to ci/publisher-dev which has limited permissions,
see dev-release security for details
Tech note. Once you create your custom GH action wrapper, make sure other repos can access it. For this go to your repo Settings > Actions > General > "Workflow permissions" > "Access" > set "Accessible from repositories in the 'mycompany' organization"