action: version resolution and binary download fail when running on GitHub #120

Closed
opened 2026-05-14 03:58:44 +00:00 by rodin · 1 comment
Owner

Problem

The composite action in .gitea/actions/review/action.yml hardcodes Gitea assumptions that break when running on GitHub Enterprise Server:

  1. REPO is hardcoded to rodin/review-bot — should be the repo hosting the action on the current server
  2. Releases API uses Gitea path format (/api/v1/repos/...) — GitHub uses /api/v3/repos/... (or REST /repos/...)
  3. Binary download URL format — Gitea: https://gitea.weiker.me/rodin/review-bot/releases/download/... vs GitHub: https://github.concur.com/strat/review-bot/releases/download/...

Observed

When running on github.concur.com runners:

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The version resolution curl hits https://github.concur.com/api/v1/repos/rodin/review-bot/releases — wrong API format and wrong repo.

Fix

The action should:

  • Detect the VCS host (Gitea vs GitHub) from github.server_url
  • Use the appropriate releases API format for each host
  • Derive the action repo from context rather than hardcoding rodin/review-bot
  • Or: accept an explicit action-repo input that defaults to the Gitea value for backward compatibility

Context

Discovered while testing GitHub support (feature/github-support) against strat/db-migrator on github.concur.com.

## Problem The composite action in `.gitea/actions/review/action.yml` hardcodes Gitea assumptions that break when running on GitHub Enterprise Server: 1. **`REPO` is hardcoded to `rodin/review-bot`** — should be the repo hosting the action on the current server 2. **Releases API uses Gitea path format** (`/api/v1/repos/...`) — GitHub uses `/api/v3/repos/...` (or REST `/repos/...`) 3. **Binary download URL format** — Gitea: `https://gitea.weiker.me/rodin/review-bot/releases/download/...` vs GitHub: `https://github.concur.com/strat/review-bot/releases/download/...` ## Observed When running on `github.concur.com` runners: ``` json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) ``` The version resolution curl hits `https://github.concur.com/api/v1/repos/rodin/review-bot/releases` — wrong API format and wrong repo. ## Fix The action should: - Detect the VCS host (Gitea vs GitHub) from `github.server_url` - Use the appropriate releases API format for each host - Derive the action repo from context rather than hardcoding `rodin/review-bot` - Or: accept an explicit `action-repo` input that defaults to the Gitea value for backward compatibility ## Context Discovered while testing GitHub support (feature/github-support) against `strat/db-migrator` on `github.concur.com`.
rodin self-assigned this 2026-05-14 03:59:06 +00:00
Author
Owner

Plan: Fix version resolution and binary download for GitHub hosts

Problem

The composite action in both .gitea/actions/review/action.yml and .github/actions/review/action.yml has three Gitea-specific assumptions that break on GitHub/GHES:

  1. REPO defaults to rodin/review-bot — on GHES the action lives in a different repo (e.g. strat/review-bot)
  2. Releases API path is Gitea-specific — uses /api/v1/repos/{owner}/{repo}/releases but GitHub uses /repos/{owner}/{repo}/releases (REST v3)
  3. Download URL format — Gitea: {server}/{repo}/releases/download/{tag}/{asset}, GitHub: {server}/{repo}/releases/download/{tag}/{asset} (same pattern but the API endpoint differs)

Constraints

  • Must remain backward-compatible — existing Gitea users with no repo input should work unchanged
  • Both .gitea and .github action files must be updated
  • The inputs.gitea-url name stays for backward compat (renaming would break callers)
  • No new binary dependencies; python3 + curl already available
  • Must work on both Gitea Actions and GitHub Actions runners

Proposed Approach

Host detection: Determine whether we're on Gitea or GitHub by checking the releases API. A simple heuristic: if github.server_url contains github.com or the /api/v3/ endpoint responds, treat it as GitHub. Otherwise assume Gitea.

Actually, a cleaner approach: use the API format that matches the host. The action can try the Gitea endpoint first, and if it fails (non-JSON response), fall back to GitHub REST API. But that's fragile.

Simplest reliable approach:

  • Add a new input action-repo that specifies where to find review-bot releases. Defaults to rodin/review-bot for backward compat.
  • Detect host type from github.server_url:
    • If it contains github.com OR returns a GitHub-style API response → GitHub mode
    • Otherwise → Gitea mode
  • Use appropriate API path based on host type:
    • Gitea: ${SERVER_URL}/api/v1/repos/${REPO}/releases?limit=1
    • GitHub: ${SERVER_URL}/api/v3/repos/${REPO}/releases?per_page=1 (GHES uses /api/v3/)
  • Download URL is the same format on both: ${SERVER_URL}/${REPO}/releases/download/${VERSION}/${BINARY}

Wait — checking the actual GitHub releases download URL format... On GHES it's: https://github.concur.com/{owner}/{repo}/releases/download/{tag}/{asset} which IS the same pattern as Gitea. So the download URL logic is fine as-is. The only real issue is the releases API path and the repo default.

Revised approach (minimal change):

  1. Add action-repo input that defaults to empty (meaning: use github.repository context)
  2. For the REPO variable: use inputs.action-repo || inputs.repo || github.repository — but wait, inputs.repo is the target repo being reviewed, not the repo hosting the action. We need to separate these.

Actually re-reading the code more carefully:

  • inputs.repo in "Run review" = the repo being reviewed (target)
  • REPO in "Determine version" and "Install review-bot" = the repo hosting review-bot releases (action source)

These are different repos and currently both default to rodin/review-bot which conflates them.

Final approach:

  1. Add action-repo input (default: empty) — the repo that hosts review-bot releases
  2. When action-repo is empty, derive it from github.action_repository (GitHub Actions provides this as the repo containing the action being run) — but Gitea Actions may not support this. Fallback: hardcode rodin/review-bot if empty (maintains backward compat for Gitea).
  3. Detect host type using a helper function:
    • Check if ${SERVER_URL}/api/v3/ path exists (GitHub/GHES)
    • Otherwise use /api/v1/ (Gitea)
    • Or simpler: just try both — use /api/v1/ if it returns valid JSON, else try /api/v3/
  4. Apply host-appropriate API path for releases query

Simplest implementation (avoiding API probing):

  • Use a new input vcs-type with values auto|gitea|github, defaulting to auto
  • auto detection: if github.server_url matches *github* → github, else → gitea
  • This handles: github.com, github.concur.com, github.yourcompany.io etc.

Implementation Details

New inputs:

action-repo:
  description: 'Repository hosting review-bot releases (owner/name). Defaults to github.action_repository on GitHub, rodin/review-bot on Gitea'
  required: false
  default: ''

"Determine version" step changes:

SERVER_URL="${{ inputs.gitea-url || github.server_url }}"
# Determine action repo (where review-bot releases live)
ACTION_REPO="${{ inputs.action-repo }}"
if [ -z "$ACTION_REPO" ]; then
  # github.action_repository gives us the repo containing this action
  ACTION_REPO="${{ github.action_repository || 'rodin/review-bot' }}"
fi

# Detect API format based on server URL
if echo "$SERVER_URL" | grep -qi "github"; then
  API_PATH="${SERVER_URL}/api/v3/repos/${ACTION_REPO}/releases?per_page=1"
else
  API_PATH="${SERVER_URL}/api/v1/repos/${ACTION_REPO}/releases?limit=1"
fi

if [ "${{ inputs.version }}" = "latest" ]; then
  VERSION=$(curl -sSf "$API_PATH" \
    | python3 -c "import sys, json; releases = json.load(sys.stdin); print(releases[0]['tag_name'] if releases else '')")
  ...
fi

"Install review-bot" step changes:

Same pattern — use ACTION_REPO and the server URL directly for download (download URL format is the same on both platforms).

"Run review" step:

Already uses inputs.repo || github.repository for the target repo. The env var names differ between .gitea (GITEA_URL/GITEA_REPO) and .github (GITHUB_SERVER_URL/GITHUB_REPOSITORY) — that's fine and intentional.

Testing Strategy

  • Verify action still works on Gitea (backward compat) — existing CI on gitea.weiker.me
  • Test the action-repo input explicitly with a GHES-style URL
  • Manual test: set gitea-url to https://github.concur.com and action-repo to strat/review-bot

Edge Cases

  • github.action_repository might not be available in Gitea Actions → fallback to rodin/review-bot
  • Server URL with trailing slash → strip it
  • GHES might use a custom domain without "github" in the name → vcs-type or action-repo input covers this

Open Questions

  • github.action_repository: Gitea Actions might support this (it emulates GitHub Actions context). Need to verify. If it does, no action-repo input needed at all — just use github.action_repository with rodin/review-bot fallback.
  • Should we support authentication for the releases API call? Currently it's unauthenticated. On GHES, releases might be in a private repo. For now, assume public releases (can add release-token input later if needed).

Completion Checklist

  1. Both .gitea and .github action files updated with host detection
  2. action-repo input added with sensible defaults
  3. Releases API uses correct path format per host type
  4. Download URL works on both Gitea and GitHub
  5. Backward compatible — existing users with no new inputs still work
  6. No new dependencies added
  7. inputs.repo (target repo for review) kept separate from action repo
## Plan: Fix version resolution and binary download for GitHub hosts ### Problem The composite action in both `.gitea/actions/review/action.yml` and `.github/actions/review/action.yml` has three Gitea-specific assumptions that break on GitHub/GHES: 1. **`REPO` defaults to `rodin/review-bot`** — on GHES the action lives in a different repo (e.g. `strat/review-bot`) 2. **Releases API path is Gitea-specific** — uses `/api/v1/repos/{owner}/{repo}/releases` but GitHub uses `/repos/{owner}/{repo}/releases` (REST v3) 3. **Download URL format** — Gitea: `{server}/{repo}/releases/download/{tag}/{asset}`, GitHub: `{server}/{repo}/releases/download/{tag}/{asset}` (same pattern but the API endpoint differs) ### Constraints - Must remain backward-compatible — existing Gitea users with no `repo` input should work unchanged - Both `.gitea` and `.github` action files must be updated - The `inputs.gitea-url` name stays for backward compat (renaming would break callers) - No new binary dependencies; python3 + curl already available - Must work on both Gitea Actions and GitHub Actions runners ### Proposed Approach **Host detection:** Determine whether we're on Gitea or GitHub by checking the releases API. A simple heuristic: if `github.server_url` contains `github.com` or the `/api/v3/` endpoint responds, treat it as GitHub. Otherwise assume Gitea. Actually, a cleaner approach: use the API format that matches the host. The action can try the Gitea endpoint first, and if it fails (non-JSON response), fall back to GitHub REST API. But that's fragile. **Simplest reliable approach:** - Add a new input `action-repo` that specifies where to find review-bot releases. Defaults to `rodin/review-bot` for backward compat. - Detect host type from `github.server_url`: - If it contains `github.com` OR returns a GitHub-style API response → GitHub mode - Otherwise → Gitea mode - Use appropriate API path based on host type: - Gitea: `${SERVER_URL}/api/v1/repos/${REPO}/releases?limit=1` - GitHub: `${SERVER_URL}/api/v3/repos/${REPO}/releases?per_page=1` (GHES uses `/api/v3/`) - Download URL is the same format on both: `${SERVER_URL}/${REPO}/releases/download/${VERSION}/${BINARY}` Wait — checking the actual GitHub releases download URL format... On GHES it's: `https://github.concur.com/{owner}/{repo}/releases/download/{tag}/{asset}` which IS the same pattern as Gitea. So the download URL logic is fine as-is. The only real issue is the **releases API path** and the **repo default**. **Revised approach (minimal change):** 1. Add `action-repo` input that defaults to empty (meaning: use `github.repository` context) 2. For the REPO variable: use `inputs.action-repo || inputs.repo || github.repository` — but wait, `inputs.repo` is the *target* repo being reviewed, not the repo hosting the action. We need to separate these. Actually re-reading the code more carefully: - `inputs.repo` in "Run review" = the repo being reviewed (target) - `REPO` in "Determine version" and "Install review-bot" = the repo hosting review-bot releases (action source) These are **different repos** and currently both default to `rodin/review-bot` which conflates them. **Final approach:** 1. Add `action-repo` input (default: empty) — the repo that hosts review-bot releases 2. When `action-repo` is empty, derive it from `github.action_repository` (GitHub Actions provides this as the repo containing the action being run) — but Gitea Actions may not support this. Fallback: hardcode `rodin/review-bot` if empty (maintains backward compat for Gitea). 3. Detect host type using a helper function: - Check if `${SERVER_URL}/api/v3/` path exists (GitHub/GHES) - Otherwise use `/api/v1/` (Gitea) - Or simpler: just try both — use `/api/v1/` if it returns valid JSON, else try `/api/v3/` 4. Apply host-appropriate API path for releases query **Simplest implementation (avoiding API probing):** - Use a new input `vcs-type` with values `auto|gitea|github`, defaulting to `auto` - `auto` detection: if `github.server_url` matches `*github*` → github, else → gitea - This handles: `github.com`, `github.concur.com`, `github.yourcompany.io` etc. ### Implementation Details #### New inputs: ```yaml action-repo: description: 'Repository hosting review-bot releases (owner/name). Defaults to github.action_repository on GitHub, rodin/review-bot on Gitea' required: false default: '' ``` #### "Determine version" step changes: ```bash SERVER_URL="${{ inputs.gitea-url || github.server_url }}" # Determine action repo (where review-bot releases live) ACTION_REPO="${{ inputs.action-repo }}" if [ -z "$ACTION_REPO" ]; then # github.action_repository gives us the repo containing this action ACTION_REPO="${{ github.action_repository || 'rodin/review-bot' }}" fi # Detect API format based on server URL if echo "$SERVER_URL" | grep -qi "github"; then API_PATH="${SERVER_URL}/api/v3/repos/${ACTION_REPO}/releases?per_page=1" else API_PATH="${SERVER_URL}/api/v1/repos/${ACTION_REPO}/releases?limit=1" fi if [ "${{ inputs.version }}" = "latest" ]; then VERSION=$(curl -sSf "$API_PATH" \ | python3 -c "import sys, json; releases = json.load(sys.stdin); print(releases[0]['tag_name'] if releases else '')") ... fi ``` #### "Install review-bot" step changes: Same pattern — use `ACTION_REPO` and the server URL directly for download (download URL format is the same on both platforms). #### "Run review" step: Already uses `inputs.repo || github.repository` for the target repo. The env var names differ between `.gitea` (GITEA_URL/GITEA_REPO) and `.github` (GITHUB_SERVER_URL/GITHUB_REPOSITORY) — that's fine and intentional. ### Testing Strategy - Verify action still works on Gitea (backward compat) — existing CI on `gitea.weiker.me` - Test the `action-repo` input explicitly with a GHES-style URL - Manual test: set `gitea-url` to `https://github.concur.com` and `action-repo` to `strat/review-bot` ### Edge Cases - `github.action_repository` might not be available in Gitea Actions → fallback to `rodin/review-bot` - Server URL with trailing slash → strip it - GHES might use a custom domain without "github" in the name → `vcs-type` or `action-repo` input covers this ### Open Questions - `github.action_repository`: Gitea Actions might support this (it emulates GitHub Actions context). Need to verify. If it does, no `action-repo` input needed at all — just use `github.action_repository` with `rodin/review-bot` fallback. - Should we support authentication for the releases API call? Currently it's unauthenticated. On GHES, releases might be in a private repo. For now, assume public releases (can add `release-token` input later if needed). ### Completion Checklist 1. Both `.gitea` and `.github` action files updated with host detection 2. `action-repo` input added with sensible defaults 3. Releases API uses correct path format per host type 4. Download URL works on both Gitea and GitHub 5. Backward compatible — existing users with no new inputs still work 6. No new dependencies added 7. `inputs.repo` (target repo for review) kept separate from action repo
rodin closed this issue 2026-05-14 07:28:46 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rodin/review-bot#120