Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 45 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,25 @@ Reusable GitHub Actions workflows forming the CI baseline for every BruzIT repos

## Features

- [Semantic Release Action](#semantic-release-composite-action)
- [Semantic Release Workflow](#reusable-semantic-release-workflow)
- [MegaLinter Workflow](#reusable-megalinter-workflow)

### Semantic Release Composite Action

[Semantic Release composite action](semantic-release/action.yaml) using the Conventional Commits preset to automate versioning, tags with SemVer and major tag, generates [GitHub releases](https://github.com/bruzit/github-actions-and-workflows/releases), and updates the [CHANGELOG](CHANGELOG.md). It checks out the repository with the GitHub App token, so the changelog commit and the major tags are pushed as the GitHub App; without `app-id` it uses `GITHUB_TOKEN`.

### Reusable Semantic Release Workflow

Reusable [Semantic Release workflow](.github/workflows/semantic-release.yaml) using the Conventional Commits preset to automate versioning, tags with SemVer and major tag, generates [GitHub releases](https://github.com/bruzit/github-actions-and-workflows/releases), and updates the [CHANGELOG](CHANGELOG.md).
Reusable [Semantic Release workflow](.github/workflows/semantic-release.yaml), similar to the [Semantic Release Action](#semantic-release-composite-action).

### Reusable MegaLinter Workflow

Reusable [MegaLinter workflow](.github/workflows/megalinter.yaml) linting pull requests with the `terraform` flavor, auto-committing fixable findings. Linters run with MegaLinter's default rules, except zizmor, whose [`zizmor.yaml`](zizmor.yaml) allows tag-pinned actions.

## Usage

### Use Semantic Release Workflow
### Use Semantic Release Action

Create a workflow, for example, `.github/workflows/semantic-release.yaml`:

Expand All @@ -33,18 +38,22 @@ on:
jobs:
release:
name: Release
uses: bruzit/github-actions-and-workflows/.github/workflows/semantic-release.yaml@v0
runs-on: ubuntu-latest
permissions:
contents: write
issues: write
pull-requests: write
with:
GH_SEM_REL_APP_ID: ${{ vars.GH_SEM_REL_APP_ID }}
semantic_release_plugins: "@semantic-release/exec" # OPTIONAL Space-separated list of additional semantic-release plugins to install.
secrets:
GH_SEM_REL_APP_PEM_FILE: ${{ secrets.GH_SEM_REL_APP_PEM_FILE }}
steps:
- name: Semantic Release
uses: bruzit/github-actions-and-workflows/semantic-release@v0
with:
app-id: ${{ vars.GH_SEM_REL_APP_ID }}
app-private-key: ${{ secrets.GH_SEM_REL_APP_PEM_FILE }}
plugins: "@semantic-release/exec" # OPTIONAL Space-separated list of additional semantic-release plugins to install.
```

The action checks out the repository itself. A local `uses: ./semantic-release` needs a prior `actions/checkout` with `persist-credentials: false`.

To create a GitHub App and a GitHub App Installation:

- GitHub
Expand Down Expand Up @@ -82,6 +91,34 @@ To create a GitHub App and a GitHub App Installation:

Configure Semantic Release in the repository, for example like this repository's [`.releaserc.yaml`](.releaserc.yaml).

### Use Semantic Release Workflow

Similar to [Use Semantic Release Action](#use-semantic-release-action), with the reusable workflow:

```yaml
---
name: Semantic Release

on:
push:
branches:
- main

jobs:
release:
name: Release
uses: bruzit/github-actions-and-workflows/.github/workflows/semantic-release.yaml@v0
permissions:
contents: write
issues: write
pull-requests: write
with:
GH_SEM_REL_APP_ID: ${{ vars.GH_SEM_REL_APP_ID }}
semantic_release_plugins: "@semantic-release/exec" # OPTIONAL Space-separated list of additional semantic-release plugins to install.
secrets:
GH_SEM_REL_APP_PEM_FILE: ${{ secrets.GH_SEM_REL_APP_PEM_FILE }}
```

### Use MegaLinter Workflow

Create `.github/workflows/megalinter.yaml`:
Expand Down
71 changes: 71 additions & 0 deletions semantic-release/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
name: Semantic Release
description: Run semantic-release with the Conventional Commits preset and move the major tags.
inputs:
app-id:
required: false
default: ''
description: GitHub App ID used to create the GitHub App token.
app-private-key:
required: false
default: ''
description: GitHub App private key used to create the GitHub App token.
plugins:
required: false
default: ''
description: Space-separated list of additional semantic-release plugins to install.
runs:
using: composite
steps:
- name: Create GitHub App token
uses: actions/create-github-app-token@v3
id: gh-app-token
if: inputs.app-id != ''
with:
app-id: ${{ inputs.app-id }}
private-key: ${{ inputs.app-private-key }}
repositories: ${{ github.repository }}
permission-contents: write
permission-issues: write
permission-pull-requests: write
- name: Checkout repository
uses: actions/checkout@v7
with:
token: ${{ steps.gh-app-token.outputs.token || github.token }}
fetch-depth: 0
persist-credentials: true
- name: Set up Node.js
uses: actions/setup-node@v7
with:
node-version: 'lts/*'
- name: Install Semantic Release # zizmor: ignore[adhoc-packages] lockfiles are not committed by design
shell: bash
env:
SEMANTIC_RELEASE_PLUGINS: ${{ inputs.plugins }}
run: |
mapfile -t plugins <<< "$SEMANTIC_RELEASE_PLUGINS"
npm install --ignore-scripts semantic-release conventional-changelog-conventionalcommits@9 @semantic-release/changelog @semantic-release/git "${plugins[@]}"
- name: Verify Semantic Release
shell: bash
run: npm audit signatures
- name: Run Semantic Release
shell: bash
env:
GITHUB_TOKEN: ${{ steps.gh-app-token.outputs.token || github.token }}
run: npx semantic-release
- name: Move major tags
if: ${{ !cancelled() }}
shell: bash
run: |
git fetch --force --prune --prune-tags origin
re='^(v(0|[1-9][0-9]*))\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(\+[0-9A-Za-z.-]+)?$'
declare -A latest=()
while read -r tag; do
[[ $tag =~ $re ]] && latest[${BASH_REMATCH[1]}]=$tag
done < <(git tag --list 'v*.*.*' --merged HEAD --sort=v:refname)
for major in "${!latest[@]}"; do
tag=${latest[$major]}
[ "$(git rev-parse -q --verify "refs/tags/$major^{commit}")" = "$(git rev-parse "$tag^{commit}")" ] && continue
git tag --force "$major" "$tag"
git push --force origin "refs/tags/$major"
done
Loading