Add GitHub provider with env-driven auto-detection#4
Merged
Conversation
Add GitHubProvider parallel to GitLabProvider, conforming to the existing Provider Protocol. Adds Settings.provider auto-detection (GITHUB_ACTIONS / GITLAB_CI env), Settings.repo for owner/repo, GitHubConfig.endpoint for Enterprise. New providers/github.py, translate_github + translate_create_tag_github_unprocessable in providers/_errors.py, current_provider selector in ioc.py mirroring the current_strategy idiom. Extracts pagination helpers to _link_pagination.py and shared _translate_transport helper at the provider-label boundary. action.yml deferred to a follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Seven-task plan derived from the 2026-06-08-github-provider design spec. Order: extract _link_pagination (pure refactor), extract _translate_transport (pure refactor), Settings.provider + validator (TDD), translate_github + 422-already-exists (TDD), GitHubProvider + integration tests (port-style), wire ioc.py + CLI + docs + README + pyproject, final validation. Resolves all five spec open items inline. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…vider_label) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dator - Add `provider` field (gitlab|github) with AliasChoices for SEMVERTAG_PROVIDER/PROVIDER - Add `repo` field with AliasChoices for SEMVERTAG_REPO/GITHUB_REPOSITORY - Add `GitHubConfig.endpoint` defaulting to "https://api.github.com" - Add `_detect_provider_from_env()` that auto-detects from GITHUB_ACTIONS/GITLAB_CI env vars, raising ValueError on ambiguous dual-CI context - Add `_resolve_provider` model_validator (mode="after") that auto-detects provider, then enforces github→repo and gitlab→project_id constraints - Add `populate_by_name=True` to Settings.model_config so field names can be used in init kwargs and apply_cli_overlay - Remove dead `project_id is None` guard in ioc._build_gitlab_provider (now enforced by validator); drop unused ConfigError import - Cascade-fix existing tests: add project_id=_PROJECT_ID_INT_SEMVERTAG to Settings() calls, update --project-id integration test to use mock-served project id 999, update project_id_missing assertion to match new validator message, add ioc test for _build_gitlab_client coverage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…_unprocessable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ioc.py: add github_client, github_provider, current_provider factories mirroring the gitlab pattern; SemvertagUseCase now consumes current_provider which dispatches on settings.provider - __main__.py: add --provider, --repo, --github-endpoint flags; --token routes to the active provider via two-pass apply_cli_overlay; MAIN_APP help string refreshed to "GitLab and GitHub repos" - tests/unit/test_ioc.py: add resolution tests for both provider paths - tests/integration/test_cli_main_verb.py: add --provider github smoke tests + GITHUB_ACTIONS auto-detection round-trip - tests/integration/test_cli_errors.py: minimal fix for cascading settings validator - docs/providers/github.md: new — auth, env vars, inline GHA workflow recipe, troubleshooting (parallel to docs/providers/gitlab.md) - mkdocs.yml: add GitHub Actions to nav - README.md: hero updated to "GitLab or GitHub"; new "Use it in GitHub Actions" section with inline workflow - pyproject.toml: description + keywords reflect dual-provider support Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CI runs on GitHub Actions, which auto-sets GITHUB_ACTIONS=true. The new Settings._resolve_provider validator picks that up and routes to the github provider — breaking every integration test that mocks GitLab endpoints (they 401 because the github auth header isn't on the GitLab-shaped mock). Tests passed locally because neither env was set. Fix: an autouse fixture in tests/conftest.py monkeypatch.delenv's both CI markers + SEMVERTAG_PROVIDER + PROVIDER before every test runs. Tests that exercise auto-detection still set them explicitly. Verified locally with both GITHUB_ACTIONS=true and GITLAB_CI=true prefixed to just test — 417 pass under both. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…er markers Previous fix only stripped GITHUB_ACTIONS / GITLAB_CI / SEMVERTAG_PROVIDER / PROVIDER. But GitHub Actions also auto-exports GITHUB_REPOSITORY (aliased into Settings.repo) and GITHUB_TOKEN (aliased into Settings.github.token), so test_provider_github_requires_repo silently failed in CI because repo was populated by the runner's env. Extract the full alias list as _HOST_CI_ENV_VARS and strip everything: provider markers, repo/project identifiers, token aliases, endpoint overrides. Verified locally with GITHUB_ACTIONS=true GITHUB_REPOSITORY=owner/repo GITHUB_TOKEN=ghp_xxx CI_PROJECT_ID=999 CI_JOB_TOKEN=glpat-xxx just test — 417 pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
GitHubProvideras a peer ofGitLabProvider. semvertag can now auto-tag GitHub repos in addition to GitLab. The package description's "Auto-tag GitLab repos" promise becomes honest: GitHub is the closing feature gap.GitHubProviderconforms to the existingProvidertyping.Protocol— same four methods, GitHub-specific endpoints (/repos/{owner}/{repo}/{...}), tag creation viaPOST /git/refs, 422-already-exists translationSettings.providerauto-detects fromGITHUB_ACTIONS/GITLAB_CIenv vars; explicit--provider githuboverrides; CI-ambiguous (both set) raisesConfigErrorSettings.repo: strfield forOWNER/REPO;GitHubConfig.endpointdefaults tohttps://api.github.com(GitHub Enterprise users override)--provider,--repo,--github-endpoint.--tokenroutes to the active provider via two-passapply_cli_overlayioc.pygainsgithub_client,github_provider,current_providerfactories — the last mirrors the existingcurrent_strategyselector pattern_link_paginationextracted as a shared module (both providers walk RFC 8288 Link headers identically);_translate_transportextracted as a shared helper parameterized onprovider_labeldocs/providers/github.mdwith inline GHA workflow recipe, token-scope guidance, GitHub Enterprise setup, troubleshootingpyproject.tomldescription + keywords reflect dual-provider supportDesign spec:
planning/specs/2026-06-08-github-provider-design.mdImplementation plan:
planning/plans/2026-06-08-github-provider.mdTest plan
just lint-ci— clean (ruff format + ruff check + ty)just test— 417 passed, 100% statement+branch coveragemkdocs build --strict— cleanGITHUB_ACTIONS=true + GITHUB_REPOSITORY=octocat/reporesolvesProvidersGroup.current_providertoGitHubProviderCI_PROJECT_ID=999(no GH env) resolvesProvidersGroup.current_providertoGitLabProviderOut of scope (follow-ups)
action.yml(GitHub Actions composite-action wrapper) — the inline-job recipe in docs/README is the supported path until the composite is published🤖 Generated with Claude Code