diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f0b2e84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,73 @@ +### macOS +# Finder metadata +.DS_Store + +# Thumbnails +._* + +# Custom folder icons +Icon + + +# Volume root files +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +### VS Code +# VSCode settings (keep shared configuration) +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### Python +# Byte-compiled files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +build/ +dist/ +*.egg-info/ +*.egg + +# dotenv environment variable files +.env + +# Virtual environments +.venv +env/ +venv/ + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.pytest_cache/ + +# Type checkers +.mypy_cache/ + +# Jupyter Notebook +.ipynb_checkpoints + +# pyenv +# .python-version diff --git a/README.md b/README.md index c04251d..0b748ac 100644 --- a/README.md +++ b/README.md @@ -9,3 +9,21 @@ # authentik Version info This repo holds the version info for the authentik built-in version check. This allows us to publish security-relevant updates without publishing the code which might expose vulnerabilities. + +## Bumping a version + +This repo is also a composite GitHub Action that bumps a product's version file (`versions///.json` and `versions//latest.json`, plus the legacy `version.json` for `authentik` itself) and opens a pull request with the change. Call it from the product's release workflow: + +```yaml +- name: Bump version + uses: goauthentik/version@main + with: + product: authentik # or e.g. authentik-agent + new-version: "2026.8.4" + changelog-url: "https://docs.goauthentik.io/releases/2026.8/#fixed-in-202684" # optional + reason: bugfix # bugfix | feature | security | other + token: ${{ steps.app-token.outputs.token }} # needs push access to this repo + commit-author: "my-app[bot] " # optional +``` + +`changelog-url` is optional: products without a docs release-notes page yet (e.g. `platform`) can omit it and the `changelog`/`changelog_url` fields are left empty. diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..7e7dc33 --- /dev/null +++ b/action.yml @@ -0,0 +1,66 @@ +name: "authentik Version Bump" +description: "Bumps the authentik version repository and opens a pull request" +inputs: + product: + description: "Product to bump" + required: true + new-version: + description: "New version number" + required: true + changelog-url: + description: "Changelog URL" + required: false + reason: + description: "Reason" + required: false + token: + description: "GitHub token with push access to the version repository" + required: true + repository: + description: "Version repository to bump" + required: false + default: "goauthentik/version" + github-app-slug: + description: "Github App slug for the bot account creating the PR" + required: true + +runs: + using: "composite" + steps: + - name: Checkout version repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v5 + with: + repository: ${{ inputs.repository }} + token: ${{ inputs.token }} + path: .version-bump + - name: Install the latest version of uv + uses: astral-sh/setup-uv@bec219d24cd3e171d82865faccec33120bb574f4 # v10.1.0 + - name: Bump + run: uv run --project ${{ github.action_path }} ${{ github.action_path }}/bump.py + shell: bash + id: bump + env: + INPUT_PRODUCT: ${{ inputs.product }} + INPUT_NEW_VERSION: ${{ inputs.new-version }} + INPUT_CHANGELOG_URL: ${{ inputs.changelog-url }} + INPUT_REASON: ${{ inputs.reason }} + ROOT: ${{ github.workspace }}/.version-bump + - id: get-user-id + name: Get GitHub app user ID + shell: bash + run: echo "user-id=$(gh api "/users/${INPUT_APP_SLUG}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" + env: + INPUT_APP_SLUG: ${{ inputs.github-app-slug }} + GH_TOKEN: ${{ inputs.token }} + - name: Create pull request + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v7 + with: + token: ${{ inputs.token }} + path: .version-bump + branch: bump-${{ inputs.product }}-${{ inputs.new-version }} + commit-message: "version: bump ${{ inputs.product }} to ${{ inputs.new-version }}" + title: "version: bump ${{ inputs.product }} to ${{ inputs.new-version }}" + body: "See ${{ steps.bump.outputs.changelog_url }}" + delete-branch: true + signoff: true + author: "${{ inputs.github-app-slug }}[bot] <${{ steps.get-user-id.outputs.user-id }}+${{ inputs.github-app-slug }}[bot]@users.noreply.github.com>" diff --git a/bump.py b/bump.py new file mode 100644 index 0000000..3473394 --- /dev/null +++ b/bump.py @@ -0,0 +1,47 @@ +from json import dumps +from os import getenv +from pathlib import Path + +from packaging.version import parse + +INPUT_PRODUCT = getenv("INPUT_PRODUCT") +INPUT_NEW_VERSION = getenv("INPUT_NEW_VERSION") +INPUT_CHANGELOG_URL = getenv("INPUT_CHANGELOG_URL") +INPUT_REASON = getenv("INPUT_REASON") +ROOT = Path(getenv("ROOT")) + +def write_output(key: str, value: str): + with open(getenv("GITHUB_OUTPUT")) as _o: + _o.write(f"{key}={value}") + +parsed_new_version = parse(INPUT_NEW_VERSION) +version_family = f"{parsed_new_version.major}.{parsed_new_version.minor}" + +# goauthentik.io/docs only has release note pages for authentik itself; other +# products (e.g. platform) don't have one to link to yet. +if not INPUT_CHANGELOG_URL and INPUT_PRODUCT == "authentik": + version_slug = INPUT_NEW_VERSION.replace(".", "") + INPUT_CHANGELOG_URL = ( + f"https://docs.goauthentik.io/releases/{version_family}/#fixed-in-{version_slug}" + ) + +data = { + "$schema": "https://version.goauthentik.io/schema.json", + "stable": { + "version": INPUT_NEW_VERSION, + "changelog": f"See {INPUT_CHANGELOG_URL}" if INPUT_CHANGELOG_URL else "", + "changelog_url": INPUT_CHANGELOG_URL or "", + "reason": INPUT_REASON, + }, +} + +version_root = ROOT / "versions" / INPUT_PRODUCT / str(parsed_new_version.major) +version_root.mkdir(parents=True, exist_ok=True) +version_file = version_root / f"{version_family}.json" +version_file.write_text(dumps(data)) +version_file.copy(ROOT / "versions" / INPUT_PRODUCT / "latest.json") +# Legacy version file +if INPUT_PRODUCT == "authentik": + (ROOT / "version.json").write_text(dumps(data)) + +write_output("changelog_url", INPUT_CHANGELOG_URL) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..04c9177 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,16 @@ +[project] +name = "authentik-version" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +authors = [ + { name = "Jens Langhammer", email = "jens@goauthentik.io" } +] +requires-python = ">=3.14" +dependencies = [ + "packaging>=26.3", +] + +[build-system] +requires = ["uv_build>=0.12.18,<0.13.0"] +build-backend = "uv_build" diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..a91e894 --- /dev/null +++ b/uv.lock @@ -0,0 +1,23 @@ +version = 1 +revision = 3 +requires-python = ">=3.14" + +[[package]] +name = "authentik-version" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "packaging" }, +] + +[package.metadata] +requires-dist = [{ name = "packaging", specifier = ">=26.3" }] + +[[package]] +name = "packaging" +version = "26.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" }, +]