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
1 change: 1 addition & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ GitHub Actions and CI/CD helpers for this repository.
|------|------|
| [`workflows/ci.yml`](workflows/ci.yml) | Umbrella **CI** — runs on push/PR to `main` and `develop` |
| [`workflows/cd.yml`](workflows/cd.yml) | **Deploy** — after CI succeeds on `develop` (staging); no `workflow_dispatch` trigger |
| [`workflows/release.yml`](workflows/release.yml) | **Release** — manual `workflow_dispatch` only; tags `main` from `pyproject.toml` (`v<version>`) and creates a GitHub Release with Weblate compatibility metadata |
| [`workflows/ci-lint.yml`](workflows/ci-lint.yml) | Lint and format (prek) |
| [`workflows/ci-test.yml`](workflows/ci-test.yml) | Unit tests and coverage |
| [`workflows/ci-package.yml`](workflows/ci-package.yml) | Build and package checks |
Expand Down
81 changes: 81 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# SPDX-FileCopyrightText: 2026 William Jin <AuraMindNest@outlook.com>
#
# SPDX-License-Identifier: BSL-1.0

name: Release

# Standalone tagging and GitHub Releases.
on:
workflow_dispatch:

permissions:
contents: write

jobs:
release:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
# actions/checkout v6.0.2
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
ref: main
fetch-depth: 0

- name: Parse versions from pyproject.toml
id: versions
run: |
set -euo pipefail
python3 <<'PY' >> "$GITHUB_OUTPUT"
import re
import tomllib
from pathlib import Path

data = tomllib.loads(Path("pyproject.toml").read_text())
plugin_version = data["project"]["version"]
weblate_version = None
for dep in data["project"]["dependencies"]:
match = re.fullmatch(r"Weblate\[all\]==(.+)", dep)
if match:
weblate_version = match.group(1)
break
if not weblate_version:
raise SystemExit("Weblate[all]== pin not found in pyproject.toml")
print(f"plugin_version={plugin_version}")
print(f"weblate_version={weblate_version}")
print(f"tag=v{plugin_version}")
PY

- name: Fail if tag already exists
run: |
set -euo pipefail
tag="${{ steps.versions.outputs.tag }}"
if git ls-remote --tags origin "refs/tags/${tag}" | grep -q .; then
echo "Tag ${tag} already exists on origin"
exit 1
fi

- name: Configure git for tag push
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"

- name: Create and push tag
run: |
set -euo pipefail
tag="${{ steps.versions.outputs.tag }}"
weblate_version="${{ steps.versions.outputs.weblate_version }}"
git tag -a "${tag}" -m "Release ${tag} (Weblate ${weblate_version})"
git push origin "${tag}"

- name: Create GitHub Release
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
tag="${{ steps.versions.outputs.tag }}"
weblate_version="${{ steps.versions.outputs.weblate_version }}"
gh release create "${tag}" \
--title "${tag} (Weblate ${weblate_version})" \
--generate-notes \
--notes "Built against Weblate ${weblate_version}."
42 changes: 42 additions & 0 deletions docs/deployment-runbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,48 @@ The full pipeline (`cd.yml`) triggers on a successful CI run against `develop`:

Concurrency is locked per branch (`cancel-in-progress: false`) so deploys never overlap.

## Release tagging

Standalone GitHub Actions workflow ([`release.yml`](../.github/workflows/release.yml)). Run it only when you want to publish a version tag and GitHub Release.

### When to run

Use **Actions → Release → Run workflow** whenever the current `main` commit should be tagged. Typical cases:

- After you are satisfied with what is on `main` (deploy or not)
- When `pyproject.toml` on `main` already has the intended `version` and Weblate pin

The workflow does not check deploy status or server health.

### What it does

1. Checks out `main` and reads [`pyproject.toml`](../pyproject.toml):
- Plugin version: `[project].version` (e.g. `1.0.0`)
- Weblate pin: `Weblate[all]==…` (e.g. `2026.5`)
2. Fails if tag `v<plugin-version>` already exists on `origin` (prevents duplicate releases)
3. Creates annotated tag `v<plugin-version>` on current `main` HEAD and pushes it
4. Creates a GitHub Release with auto-generated notes, title `v<version> (Weblate <pin>)`, and body noting Weblate compatibility

Use the release title and body to verify which Weblate version the tagged tree was built against.

### Prerequisites

- `version` in `pyproject.toml` on `main` must be the release you intend (bump on `develop` and promote, or commit on `main`, before running)
- Tag `v<version>` must not already exist

### Failure modes

| Failure | Likely cause |
|---------|----------------|
| Tag already exists | Re-ran without bumping `version` in `pyproject.toml` |
| Wrong release contents | `main` HEAD did not include the expected `pyproject.toml` |
| `gh release create` failed | Permissions or network; check whether the tag was pushed and finish the release manually on GitHub |

### Important

- Tagging and GitHub Releases **do not deploy** or change servers
- Deleting a GitHub Release **does not roll back** a deploy; reverting production is a separate server/git operation (see deploy sections above)

## Troubleshooting

### Container stays unhealthy
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ license-files = ["LICENSE"]
name = "cppa-weblate-plugin"
readme = "README.md"
requires-python = ">=3.12"
version = "0.1.0"
version = "1.0.0"

[project.optional-dependencies]
dev = [
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.