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
94 changes: 0 additions & 94 deletions .github/workflows/publish-pypi.yml

This file was deleted.

9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Workflows

Reusable GitHub Actions workflows for common CI/CD tasks, designed to be easily integrated into your projects.

See the [docs](./docs/) for detailed documentation on each workflow, including parameters, usage instructions, and best practices.

See the [samples](./samples/) for example workflows demonstrating how to use these reusable workflows in real-world scenarios.

Note - this repository uses its own workflows to release, so you can check out the [release workflow](./.github/workflows/release.yaml) for a real example of how to use these workflows together in a complete release pipeline.
80 changes: 80 additions & 0 deletions docs/samples/release.container.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Release Container Workflow Sample

This sample workflow demonstrates a complete release pipeline that combines semantic versioning, container publishing, and automated tagging. It's designed to be copied into your project's `.github/workflows/` directory and customised for your specific needs.

The idea is to provide a drop-in model for releasing software, where developers can focus on code, rather than the mechanics of releases. The developer only has to make the decision of what type of release (patch, minor, major, none) and communicate this through their PR title. The workflow then takes care of the rest - generating release notes, creating GitHub releases, building and publishing container images, and tagging them appropriately.

This exists within the existing constraints of Github, mostly that [automated releases cannot trigger other workflows](https://github.com/orgs/community/discussions/25281), so by composing reusable workflows together we can achieve a full release pipeline that is still easy to understand and maintain. The workflow is also designed to be flexible, so you can easily swap out the container publishing step for other types of release artifacts if needed.

## Overview

The workflow performs the following steps:

1. **Semantic Release**: Analyses commits since the last release to determine if a new version should be created, and if so, generates a new Github release with an automatically generated changelog.
2. **Container Publishing**: Builds and pushes a container image with an `edge` tag (we avoid latest, so this is a pre-release build)
3. **Semver Tagging**: If a release was created, promotes the edge image to semantic version tags (e.g., `1.2.3`, `1.2`, `1`)

## Prerequisites

- Your repository must follow [conventional commit](https://conventionalcommits.org/) format
- We recommend `samples/check.pr-title.yaml` to enforce this on pull requests
- Your repository settings should only allow squash merges, and use the PR title as the commit message for commit messages to be correctly parsed by semantic-release
- You need a `samples/release.config.js` in your repository root to configure semantic-release
- You need a `Dockerfile` in your repository root (or update the `dockerfile` parameter)

## Workflow Jobs

### semantic-release

Uses the [`semantic-release.yml`](../semantic-release.md) reusable workflow to:

- Install and run semantic-release
- Create GitHub releases with automatically generated changelogs
- Output `release-created` (boolean) and `release-tag` (version string)

### publish-container

Uses the [`publish-container.yml`](../publish-container.md) reusable workflow to:

- Build a multi-architecture container image
- Tag it with SHA, timestamp, and "edge"
- Push to the specified container registry

**Parameters:**

- `image-name`: Name of your container image
- `image-description`: Description for the image
- `registry`: Container registry (e.g., `ghcr.io`, `docker.io`)
- `context`: Build context path (usually `.`)
- `dockerfile`: Path to Dockerfile
- `platforms`: Target architectures (comma-separated)

### semver-container

Uses the [`semver-container.yml`](../semver-container.md) reusable workflow to:

- Promote the edge image to semantic version tags
- Only runs if `semantic-release` created a new release

**Parameters:**

- `image-name`: Must match the `publish-container` job
- `registry`: Must match the `publish-container` job
- `tag`: Release tag from semantic-release (do not modify)

### Version Pinning

For production use, pin to specific versions:

```yaml
uses: health-informatics-uon/workflows/.github/workflows/semantic-release.yml@v1.3.0
```

Check the [releases](https://github.com/health-informatics-uon/workflows/releases) for available versions.

## Usage

1. Copy `samples/release.container.yaml` to your repository's `.github/workflows/release.yaml`
2. Copy `samples/release.config.js` to your repository root and customise it for your repository
3. Update the workflow parameters in `release.yaml` (image name, etc.)
4. Ensure your repository follows the prerequisites (conventional commits, squash merges, etc.)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
10 changes: 10 additions & 0 deletions samples/check.dependency-review.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: 'Dependency Review'
on: [pull_request]

permissions:
contents: read

jobs:
dependency-review:
uses: health-informatics-uon/workflows/.github/workflows/dependency-review.yml@1.3.0
secrets: inherit
15 changes: 15 additions & 0 deletions samples/check.pr-title.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: 'Check PR title'

on:
pull_request:
types:
- opened
- reopened
- edited
- synchronize

jobs:
main:
uses: health-informatics-uon/workflows/.github/workflows/pr-title.yml@1.3.0
permissions:
pull-requests: read
54 changes: 54 additions & 0 deletions samples/publish.pypi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# This workflow will upload a Python Package using Twine when a release is created
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries

name: Upload Python Package

on:
release:
types: [published]

permissions:
contents: read

jobs:
build:
name: Build distribution
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.x"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Store the distribution packages
uses: actions/upload-artifact@v4
with:
name: python-package-distributions
path: dist/

publish-to-pypi:
name: Publish Python distribution to PyPI
needs:
- build
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/omop-lite
permissions:
id-token: write

steps:
- name: Download all the dists
uses: actions/download-artifact@v4
with:
name: python-package-distributions
path: dist/
- name: Publish distribution 📦 to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
13 changes: 13 additions & 0 deletions samples/release.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module.exports = {
"branches": ["main"],
"tagFormat": "${version}",
"preset": "angular",
"repositoryUrl": "https://github.com/Health-Informatics-UoN/<YOUR_REPO_NAME>.git",
plugins: [
'@semantic-release/commit-analyzer',
'@semantic-release/release-notes-generator',
'@semantic-release/exec',
'@semantic-release/github',
],
"initialVersion": "1.0.0"
};
51 changes: 51 additions & 0 deletions samples/release.container.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Sample workflow for releasing a project using reusable workflows from health-informatics-uon/workflows
# This demonstrates how to combine semantic-release, container publishing, and semver tagging
# Customize the placeholders and values below for your specific project

name: Release
permissions:
contents: write
pull-requests: write
issues: write
packages: write
id-token: write

on:
push:
branches:
- main

jobs:
release:
uses: health-informatics-uon/workflows/.github/workflows/semantic-release.yml@1.3.0
with:
node-version: '24'
secrets: inherit

publish-container:
uses: health-informatics-uon/workflows/.github/workflows/publish-container.yml@1.3.0
with:
# Set your container image name
image-name: <YOUR_IMAGE_NAME>
# Describe your container image
image-description: '<YOUR_IMAGE_DESCRIPTION>'
registry: ghcr.io
# Path to the build context (usually '.')
context: .
# Path to your Dockerfile
dockerfile: Dockerfile
# Target platforms for multi-architecture builds
platforms: linux/amd64,linux/arm64
secrets: inherit

semver-container:
uses: health-informatics-uon/workflows/.github/workflows/semver-container.yml@1.3.0
needs: [release, publish-container]
if: needs.release.outputs.release-created == 'true'
with:
# Your container image name (must match publish-container)
image-name: <YOUR_IMAGE_NAME>
registry: ghcr.io
# Release tag from semantic-release (do not change)
tag: ${{ needs.release.outputs.release-tag }}
secrets: inherit
Loading