fix(ci): replace gh api REST passthroughs with Gitea-compatible shapes (#75 class D) #81
Closed
claude-ceo-assistant
wants to merge 7 commits from
fix/issue75-class-D-gh-api-to-gitea-rest into main
pull from: fix/issue75-class-D-gh-api-to-gitea-rest
merge into: molecule-ai:main
molecule-ai:main
molecule-ai:fix/175-env-matched-pair-guard
molecule-ai:fix/vitest-pool-worker-startup-timeouts
molecule-ai:refactor/sop-tier-check-extract-script
molecule-ai:fix/sop-tier-check-pr-target-security
molecule-ai:ci/sop-tier-check-deploy
molecule-ai:fix/issue53-admin-token-pair-guard
molecule-ai:fix/org-import-started-event-name
molecule-ai:refactor/delete-uses-cascade-helper
molecule-ai:fix/org-import-reconcile-and-audit
molecule-ai:fix/preserve-model-secret-on-restart
molecule-ai:feat/persona-bind-mount-local-dev
molecule-ai:feat/canary-tier-filter
molecule-ai:feat/plugin-version-subscription
molecule-ai:feat/plugin-hot-reload-classifier
molecule-ai:feat/plugin-atomic-install
molecule-ai:feat/air-hot-reload-dev
molecule-ai:feat/persona-env-injection
molecule-ai:fix/external-resolver-hardening
molecule-ai:fix/cherry-3-files-vitest-postgres-e2eapi
molecule-ai:fix/promote-vitest-postgres-fixes
molecule-ai:fix/saas-plugin-install-eic
molecule-ai:fix/issue-94-e2e-api-parallel-safe-class-b
molecule-ai:migrate/issue-71-vanity-imports
molecule-ai:fix/handlers-postgres-port-collision-class-b
molecule-ai:fix/issue-96-canvas-vitest-cold-start-timeout
molecule-ai:fix/hermes-agent-doc-gitea-migration
molecule-ai:fix/196-retarget-main-to-staging-gitea-rest
molecule-ai:fix/gitea-ci-flakes-issue-88
molecule-ai:fix/pin-upload-artifact-v3-gitea
molecule-ai:fix/issue-72-auto-sync-token-canary-v2
molecule-ai:fix/issue75-class-F-gh-run-list-to-statuses
molecule-ai:fix/issue75-class-A-gh-pr-to-gitea-rest
molecule-ai:feat/issue-63-local-build-from-gitea-v2
molecule-ai:fix/195-auto-promote-staging-gitea-rest
molecule-ai:fix/144-branch-protection-check-name-parity-audit
molecule-ai:fix/harness-replays-pre-clone-manifest
molecule-ai:chore/trigger-auto-sync-verification
molecule-ai:fix/codeql-stub-on-gitea-156
molecule-ai:chore/issue173-retrigger-after-ecr-repo-create
molecule-ai:fix/issue173-inline-aws-ecr-login
molecule-ai:fix/issue173-shell-docker-push
molecule-ai:chore/retrigger-harness-replays-post-class-g
molecule-ai:fix/issue173-buildx-driver-and-cache
molecule-ai:fix/post-suspension-clone-manifest
molecule-ai:fix/issue173-followup-platform-dockerfile
molecule-ai:fix/post-suspension-github-urls
molecule-ai:fix/170-goroutine-bleed-test-isolation
molecule-ai:fix/issue173-publish-workspace-server-image
molecule-ai:fix/issue36-a2a-proxy-preflight
molecule-ai:fix/codeql-continue-on-error-156
molecule-ai:feat/demo-mock-3-bigorg-mock-runtime
molecule-ai:feat/demo-mock-1-purchase-success-modal
molecule-ai:fix/publish-path-filter-add-scripts
molecule-ai:fix/clone-manifest-gitea
molecule-ai:chore/touch-publish-workflow-to-trigger
molecule-ai:chore/retrigger-publish-post-aws-secrets
molecule-ai:chore/cherry-pick-pr23-into-main
molecule-ai:chore/backsync-main-into-staging-task-166
molecule-ai:fix/auto-sync-use-devops-token
molecule-ai:chore/retrigger-staging-on-fixed-runner-image
molecule-ai:chore/drop-github-app-auth-and-ecr-swap
molecule-ai:docs/readme-comprehensive-refresh-2026-05-06
molecule-ai:feat/rfc-2945-pr-c-2-canvas-chat-history
molecule-ai:fix/issue10-runtime-aware-plugin-install
molecule-ai:fix/s8-bind-loopback-dev
molecule-ai:fix/14-cascade-gitea-dispatch
molecule-ai:docs/molecule-core-bulk-sed
molecule-ai:chore/pin-artifact-actions-v3
molecule-ai:fix/lowercase-org-slug
molecule-ai:fix/script-ghcr-and-lint-paths
molecule-ai:docs/workspace-runtime-readme-source-edit
molecule-ai:feat/eic-tunnel-pool-core-11
molecule-ai:chore/rfc-2945-pr-c-3-delete-historyhydration
molecule-ai:fix/2872-sqlmock-regex-tightening
molecule-ai:fix/cp-orphan-sweeper-2989
molecule-ai:feat/registry-prefix-env-driven-issue-6
molecule-ai:docs/readme-refresh-2026-05-06
No reviewers
Labels
No Label
tier:high
tier:low
tier:medium
Milestone
Clear milestone
No items
No Milestone
Projects
Clear projects
No project
Assignees
Clear assignees
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.
No due date set.
Dependencies
No dependencies set.
Reference: molecule-ai/molecule-core#81
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
No description provided.
Delete Branch "fix/issue75-class-D-gh-api-to-gitea-rest"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Class D of the post-#66 sweep tracked in #75: replace
gh apiREST passthroughs with the Gitea-shape that actually works. Three files, three different fix patterns because each underlying capability has a different relationship with Gitea's API surface.Why
gh apicalls hit/api/v3/...(GitHub Enterprise REST shape). Gitea exposes/api/v1/. SettingGH_HOSTdoes not help — the path is hardcoded ingh. So everygh api ...call returns 404. Per #75 audit + 2026-05-07 endpoint probe.Files + fix shape
auto-promote-on-e2e.ymlgh api repos/.../compare/A...Breturning.statusactions/checkout fetch-depth=200+git merge-base --is-ancestor(Gitea's/comparedoes NOT accept full SHAs — verified empirically 2026-05-07)ci.yml(canvas-deploy-reminder)gh api -X POST repos/.../commits/{sha}/comments$GITHUB_STEP_SUMMARY(Gitea has NO commit-comments endpoint — verified 404 2026-05-07)check-merge-group-trigger.ymlgh api .../branches/X/protection/required_status_checksto lint merge_group triggerTest plan
git merge-base --is-ancestorancestry semantics match GitHub compare API status semantics bit-exact: ahead=current-is-ancestor-of-target, behind=target-is-ancestor-of-current, diverged=neither/compare/A...Bworks on branch/tag refs but returnsBaseNotExiston full SHAs — justifying the local-git approach/commits/{sha}/commentsis 404 on GiteaHostile self-review — three weakest spots
fetch-depth: 200may be insufficient if:latestfalls catastrophically behind. 200 commits ≈ ~1 week of main activity at current cadence; if a multi-week cron pause leaves :latest pointing at an older revision, the ancestry compute falls into theerrorbranch and the workflow goes red instead of silently mispromoting. That's the safer failure mode, but worth documenting as a tunable.Security + version impact
ci.ymldeploy-reminder permission tightens fromcontents: write→contents: read(least-privilege; no longer needs to write commit comments)Closes part of #75
Companion PRs: #80 (class A), upcoming class F.
🤖 Generated with Claude Code
Part of the post-#66 sweep to remove `gh` CLI dependencies that fail silently against Gitea (which exposes /api/v1 only — no GraphQL → 405, no /api/v3 → 404). Class D covers `gh api` REST passthroughs that either have a Gitea v1 equivalent at a different path/shape or no equivalent at all. Three files in this class, each with a different fix shape because each underlying Gitea capability is different: `auto-promote-on-e2e.yml` (compute SHA ancestry): Old: `gh api repos/.../compare/A...B` returning `.status` (ahead|behind|identical|diverged). Gitea: `/api/v1/repos/.../compare/A...B` accepts only branch / tag refs — full commit SHAs return `BaseNotExist`. So even a "translate the URL" rewrite would fail. Verified empirically 2026-05-07: branches/tags work, SHAs don't. Fix: Add `actions/checkout@v6 fetch-depth=200` + use `git merge- base --is-ancestor` locally. Exact same four-bucket semantics (ahead | behind | diverged | error), zero cross-host API dependency. Same pattern PR #66 used for auto-sync. The 200- commit depth comfortably covers any realistic divergence between :latest and a candidate retag (promotes are minutes apart, not hundreds of commits). `ci.yml` (canvas-deploy-reminder commit comment): Old: `gh api -X POST repos/.../commits/{sha}/comments` posting a deploy-reminder body for the operator. Gitea: NO commit-comments endpoint exists — `/repos/.../commits/ {sha}/comments` returns 404 (verified 2026-05-07). Gitea only exposes `/commits/{sha}/statuses` for commit-level surface, which is the wrong shape for a free-form reminder. Fix: Drop the API call. Write the reminder body to `$GITHUB_STEP_SUMMARY` instead. The reminder is entirely operator-facing and is just as discoverable on the run summary page (which an operator naturally lands on when they need to action a deploy). Commit comments were a stale UI artefact of the GitHub era, not a load-bearing automation surface. Permission: drop `contents: write` (no longer needed) → `read`, smallest scope per least-privilege. `check-merge-group-trigger.yml` (merge_group: trigger linter): Old: `gh api .../branches/staging/protection/required_status_checks` reading the contexts list, then walking workflow files. Gitea: branch-protection API is at /api/v1/repos/.../branch_ protections/{name} (different path) with `status_check_ contexts` (different field name) — but the entire workflow only existed to lint that workflows producing a required check declare a `merge_group:` trigger, which is needed because GitHub's merge queue dead-locks at AWAITING_CHECKS when the trigger is missing. Gitea has NO merge queue, NO gh-readonly-queue/... ref shape, NO merge_group event semantics. The dead-lock pattern this linter catches cannot occur on Gitea by construction. Fix: Convert to no-op stub (same pattern as the CodeQL stub landed in PR #51). Workflow name + trigger surface preserved so any external referrer (none confirmed via the 2026-05-07 branch-protection audit) keeps resolving. Re-enable path documented in the file header for if/when Gitea grows a merge queue. curl invocation pattern: `curl --fail-with-body -sS` (NOT `-fsS` — the two short-fail flags are mutually exclusive in modern curl). Token model: workflows continue to use act_runner's GITHUB_TOKEN where they still need API access (`auto-promote-on-e2e.yml`'s checkout uses the runner's default token; `ci.yml` no longer needs any API auth for the deploy-reminder step; `check-merge-group- trigger.yml` no longer makes any API calls). Verification: - YAML syntax validates for all three files. - Live curl against Gitea confirms `/compare/A...B` accepts branch refs (200, total_commits=N) and refuses full SHAs (404, BaseNotExist) — justifying the local-git approach. - `/repos/.../commits/{sha}/comments` confirmed 404 on Gitea. - `git merge-base --is-ancestor` exit-code semantics match the GitHub compare API status semantics exactly: ahead = current is ancestor of target; behind = target is ancestor of current; diverged = neither. Closes part of #75. Class A landed in #80; class F (gh run list → no Gitea workflow-runs API at all) lands in a separate PR. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>gh-CLI sweep class D (gh api REST passthroughs). auto-promote-on-e2e.yml (compare→git merge-base), ci.yml (commit-comment→step summary), check-merge-group-trigger.yml (no-op stub — Gitea has no merge queue). YAML validates; bit-exact-equivalent ancestry semantics verified. 0 failures. Ready.
New commits pushed, approval review dismissed automatically according to repository settings
Closing as stale during 2026-05-09 triage. mergeable=False due to base conflicts, plus the lone approval is from
Ghost(deleted-user) so the gate isn't satisfiable as-is. Class D (gh-CLI passthrough cleanup) work is tracked in tasks #195-#197; reopen + rebase if there's a remaining gap not covered by those.— claude-ceo-assistant (triage)
Pull request closed