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
34 changes: 34 additions & 0 deletions .github/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name-template: "$RESOLVED_VERSION"
tag-template: "$RESOLVED_VERSION"
version-template: "$MAJOR.$MINOR.$PATCH"
version-resolver:
major:
labels:
- "semver:major"
minor:
labels:
- "semver:minor"
patch:
labels:
- "semver:patch"
default: patch
categories:
- title: "Features"
labels:
- feature
- enhancement
- title: "Bug Fixes"
labels:
- bug
- fix
- title: "Maintenance"
labels:
- chore
- maintenance
- refactor
- dependencies
- documentation
change-template: "- $TITLE (#$NUMBER) @$AUTHOR"
no-changes-template: "No user-facing changes."
exclude-labels:
- skip-changelog
22 changes: 22 additions & 0 deletions .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Draft Release Notes

on:
push:
branches:
- master
workflow_dispatch:

permissions:
contents: read

jobs:
update_release_draft:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read

steps:
- uses: release-drafter/release-drafter@v6
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
112 changes: 112 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Publish Release

on:
push:
tags:
- "*.*.*"
workflow_dispatch:

permissions:
contents: read
id-token: write

env:
PYTHON_VERSION: "3.12"

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

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}

- name: Install build backend
run: |
python -m pip install --upgrade pip
pip install build

- name: Build package
run: python -m build

- name: Upload dist artifact
uses: actions/upload-artifact@v4
with:
name: syncmymoodle-dist
path: dist/*
if-no-files-found: error

publish-testpypi:
name: Publish to TestPyPI
runs-on: ubuntu-latest
needs: build
environment:
name: testpypi
url: https://test.pypi.org/p/syncMyMoodle
permissions:
id-token: write

steps:
- uses: actions/download-artifact@v4
with:
name: syncmymoodle-dist
path: dist

- name: Upload to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

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

steps:
- uses: actions/download-artifact@v4
with:
name: syncmymoodle-dist
path: dist

- name: Upload to PyPI
uses: pypa/gh-action-pypi-publish@release/v1

github-release:
name: Create GitHub release
runs-on: ubuntu-latest
needs: publish-pypi
if: ${{ needs.publish-pypi.result == 'success' }}
permissions:
contents: write

steps:
- uses: actions/download-artifact@v4
with:
name: syncmymoodle-dist
path: dist

- name: Publish curated release notes
id: publish_release
uses: release-drafter/release-drafter@v6
with:
publish: true
tag: ${{ github.ref_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Upload release artifacts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release upload ${{ github.ref_name }} dist/* --clobber
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,8 @@ in the configuration file.
If everything went alright, you won't need to enter your password again
in the future, as it will be obtained automatically and securely from
the Secret Service Integration.


## Maintenance

Information to create releases and publish them can be found in `docs/releasing.md`.
54 changes: 54 additions & 0 deletions docs/releasing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Releasing syncMyMoodle

There are two GitHub Actions workflows that do publishing and prepare release notes.

## Release Drafter workflow

Every push to `master` has it's information go into `release-drafter.yml`, which updates the draft release on GitHub. Labels drive what happens:

- `feature`, `bug`, `maintenance`, `dependencies`, `documentation`, etc. decide
which section a PR lands in.
- `semver:major`, `semver:minor`, `semver:patch` hint at the next version bump.
- `skip-changelog` hides a PR completely.

Before you tag a release, open the draft on GitHub and tweak the wording. Do it
close to tagging so new merges don't overwrite your edits.

## Publish Release workflow

`release.yaml` runs on tags that look like our versions (`0.2.3`, `0.2.3.post1`,
`0.3.0-rc.1`, ...) or when you trigger it manually. The job order:

1. Build sdist + wheel via `python -m build`.
2. Push both archives to TestPyPI and PyPI using Trusted Publishing (OIDC).
3. Publish the curated release draft and upload the built artifacts to it.

Since this uses Trusted Publishing you don't need API tokens, but PyPI/TestPyPI
must trust the workflow first.

## Trusted Publishing setup

(this is already done)

1. On PyPI and TestPyPI open **Manage project -> Publishing**.
2. Click **Add a trusted publisher -> GitHub Actions**.
3. Point it at this repo, the workflow `.github/workflows/release.yaml`, and the
matching environment (`pypi` or `testpypi`).
4. After the first workflow run, approve the pending publisher in the UI once.

## Release todos

1. Merge PRs with the right labels and useful titles for the release note draft.
2. Bump the version in `pyproject.toml`.
3. Commit and tag using the version string (`X.Y.Z`, `X.Y.Z.postN`, etc.):
```bash
git tag 0.2.4
git push origin 0.2.4
```
4. Watch the "Publish Release" workflow. Approve the Trusted Publishing request
on PyPI/TestPyPI if one pops up (didn't have that happen for me yet).
5. Once it's green, PyPI/TestPyPI have the new files and the GitHub release is
live with the release notes + artifacts.

To re-run the workflow, use the Actions
tab -> **Publish Release -> Run workflow**.