Skip to content

0.3.0 — GitHub provider

Choose a tag to compare

@lesnik512 lesnik512 released this 08 Jun 17:32
· 60 commits to main since this release
24b330e

Feature release. Adds first-class GitHub support. semvertag now auto-tags both GitLab projects and GitHub repos from the same CLI, with auto-detection from the CI runner's environment. The package description "Auto-tag GitLab repos" becomes "Auto-tag GitLab and GitHub repos" — honest at last.

If you're on GitLab today, nothing changes: the default provider remains gitlab when no CI env signals otherwise. Drop straight to "What's new" — there are no breaking changes to the GitLab side.

What's new

  • GitHubProvider. Parallel to GitLabProvider, conforming to the same four-method Provider Protocol. Talks to api.github.com (or your GitHub Enterprise endpoint via SEMVERTAG_GITHUB__ENDPOINT), authenticates via Authorization: Bearer <token> + X-GitHub-Api-Version: 2022-11-28, creates tags via POST /repos/{owner}/{repo}/git/refs. Same retry posture, same decoder path, same error translator shape as the GitLab side — built on the httpware-backed infrastructure that landed in 0.2.x.
  • Provider auto-detection from CI env. semvertag reads GITHUB_ACTIONS and GITLAB_CI to pick the active provider. Inside GitHub Actions: GITHUB_ACTIONS=true is auto-set → provider=github. Inside GitLab CI: GITLAB_CI=trueprovider=gitlab. Outside CI: defaults to gitlab (back-compat with 0.2.x users). Explicit --provider github or SEMVERTAG_PROVIDER=github always wins.
  • New CLI flags.
    • --provider github|gitlab — explicit override
    • --repo OWNER/REPO — GitHub repo identifier (or set GITHUB_REPOSITORY / SEMVERTAG_REPO)
    • --github-endpoint — GitHub API endpoint (for GitHub Enterprise)
    • --token now routes to the active provider's token field (a --provider github --token ghp_... invocation populates Settings.github.token)
  • New env aliases picked up by pydantic-settings:
    • GITHUB_REPOSITORY, SEMVERTAG_REPOSettings.repo
    • SEMVERTAG_PROVIDER, PROVIDERSettings.provider
    • GITHUB_TOKEN, SEMVERTAG_GITHUB__TOKEN, SEMVERTAG_TOKENSettings.github.token
    • SEMVERTAG_GITHUB__ENDPOINTSettings.github.endpoint (default https://api.github.com)
  • Tag-already-exists detection on GitHub. GitHub returns 422 Unprocessable Entity with {"errors": [{"resource": "Reference", "code": "already_exists"}]} when you POST a tag ref that already exists. translate_create_tag_github_unprocessable inspects both the structured already_exists code (durable contract) and the "already exists" message string (safety net) and surfaces as a ConfigError ("Tag already exists: 'vX.Y.Z'.").
  • Inline GitHub Actions workflow recipe in docs/providers/github.md and README.md. Uses actions/setup-python + uvx semvertag tag. Workflow needs permissions: contents: write to use the auto-issued GITHUB_TOKEN; or supply a PAT with contents: write (fine-grained) / repo / public_repo (classic) as SEMVERTAG_TOKEN.

What's new under the hood

Internal cleanups that landed alongside the provider:

  • _link_pagination module — RFC 8288 Link-header walking extracted from providers/gitlab.py (GitHub paginates identically; one helper now serves both).
  • _translate_transport shared helper in providers/_errors.py — the transport-error translation branches (DecodeError, TimeoutError, NetworkError, RetryBudgetExhaustedError, fallback) were uniformly "<provider> <description>" between GitLab and GitHub, so they parameterize cleanly on provider_label: str. Per-status translation stays per-provider because the actionable hints differ.
  • Settings._resolve_provider validator — runs at construction time; auto-detects from env if Settings.provider is unset; enforces that provider=github requires repo and provider=gitlab requires project_id. Replaces the runtime guards that used to live in ioc.py.

Behavior notes

  • Settings() now requires either project_id (gitlab) or repo (github). Pre-0.3.0 you could construct Settings() with neither, and the runtime guard in ioc._build_gitlab_provider would raise ConfigError("Project id missing. ...") at provider-construction time. The new validator catches the same situation earlier with a clearer message. CI consumers were already setting CI_PROJECT_ID (auto-exported by GitLab CI) so this is enforcing what was implicitly required. Local-dev users running semvertag tag against gitlab.com with no --project-id will see the new validator message instead of the old one. Same exit code (2), more actionable diagnostic.
  • No retry-policy changes. Retry middleware, backoff, status codes, RetryBudget all unchanged from 0.2.x.
  • No CLI flag removals. All 0.2.x flags still work. Three new ones added; --token semantics extended to route by active provider.

Migration

For most users, no migration needed. GitLab callers see no behavior change.

To start using GitHub:

# .github/workflows/semvertag.yml
name: semvertag
on:
  push:
    branches: [main]
permissions:
  contents: write
jobs:
  tag:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 0 }
      - uses: actions/setup-python@v5
        with: { python-version: "3.13" }
      - run: pip install --quiet 'uv>=0.4,<1'
      - run: uvx 'semvertag>=0.3,<1' tag
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

GITHUB_ACTIONS=true auto-resolves --provider github; GITHUB_REPOSITORY auto-resolves --repo. The minimum workflow above is the complete setup for github.com-hosted public/private repos using the workflow-scoped GITHUB_TOKEN.

See docs/providers/github.md for token scopes, fine-grained vs classic PATs, GitHub Enterprise setup, and troubleshooting.

See also

Known follow-ups

  • action.yml composite GitHub Action. A one-line uses: modern-python/semvertag@vX.Y.Z is nicer DX than the inline workflow. Deferred; the inline recipe is the supported path until the composite ships.
  • Bitbucket provider. Same pattern; separate work.
  • GitHub App authentication. PATs and the workflow-scoped GITHUB_TOKEN are supported; GitHub App JWT exchange is not.