2 Commits
v7 .. v9

Author SHA1 Message Date
Markus Hofstetter cd77158577 feat: add server_url input to override auto-detected API server URL
Allows specifying internal routing addresses for Gitea/GitHub API calls (e.g., http://server:3000), addressing container network restrictions when external URLs are not routable.
2026-06-13 11:30:02 +02:00
Markus Hofstetter 7e6b266c34 fix: resolve PR number from event payload for Gitea Actions
Gitea Actions mirrors GitHub Actions env vars and does not expose a flat
GITEA_EVENT_PULL_REQUEST_NUMBER. Parse the PR number out of
$GITHUB_EVENT_PATH, key platform detection on $GITEA_ACTIONS, and use
the correct Accept header for GitHub's diff endpoint.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-22 23:58:38 +02:00
3 changed files with 55 additions and 46 deletions
+4
View File
@@ -18,6 +18,10 @@ inputs:
description: "Custom API base URL (for OpenAI-compatible providers). Ignored for built-in providers."
required: false
default: ""
server_url:
description: "Override the Gitea/GitHub server URL used for API calls (e.g. http://server:3000 for internal routing inside the runner). Defaults to the auto-detected server URL."
required: false
default: ""
token:
description: "Git platform token for posting PR comments"
required: true
+1
View File
@@ -11,6 +11,7 @@ export PI_API_KEY="${INPUT_API_KEY}"
export PI_PROVIDER="${INPUT_PROVIDER:-zai}"
export PI_MODEL="${INPUT_MODEL:-glm-5.1}"
export PI_BASE_URL="${INPUT_BASE_URL:-}"
export PI_SERVER_URL="${INPUT_SERVER_URL:-}"
export PI_TOOLS="${INPUT_TOOLS:-read,grep,find,ls}"
export PI_REVIEW_PROMPT="${INPUT_REVIEW_PROMPT:-}"
export PI_EXCLUDE="${INPUT_EXCLUDE_PATTERNS:-*.lock package-lock.json yarn.lock pnpm-lock.yaml *.min.js *.min.css *.map}"
+50 -46
View File
@@ -78,20 +78,44 @@ echo "Generate diff"
# Instead, we get the diff directly from the Gitea/GitHub API using the token
# we already have for posting comments.
# Detect platform and resolve PR info
if [ -n "${GITEA_SERVER_URL:-}" ]; then
API_BASE="${GITEA_SERVER_URL}/api/v1"
PR_NUMBER="${GITEA_EVENT_PULL_REQUEST_NUMBER:-}"
REPO="${GITEA_REPOSITORY:-}"
echo "Platform: Gitea (${GITEA_SERVER_URL})"
# Gitea Actions mirrors GitHub Actions env vars ($GITHUB_*) and exposes the
# event payload at $GITHUB_EVENT_PATH. There is no flat $GITEA_EVENT_*
# variable for the PR number, so we parse it out of the event JSON.
REPO="${GITHUB_REPOSITORY:-${GITEA_REPOSITORY:-}}"
# Detect Gitea vs GitHub. Gitea sets $GITHUB_SERVER_URL too, so the only
# reliable signal is $GITEA_ACTIONS (or a non-github.com server URL).
#
# $PI_SERVER_URL (server_url input) overrides the auto-detected server URL.
# Gitea reports its *external* hostname (e.g. git.example.com), which may not
# be routable from inside the runner's container network. Setting server_url
# to the internal address (e.g. http://server:3000) fixes API calls.
SERVER_URL="${PI_SERVER_URL:-${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-}}}"
if [ -n "${GITEA_ACTIONS:-}" ] || { [ -n "$SERVER_URL" ] && [ "${SERVER_URL#*github.com}" = "$SERVER_URL" ]; }; then
API_BASE="${SERVER_URL}/api/v1"
PLATFORM="gitea"
echo "Platform: Gitea (${SERVER_URL})"
else
API_BASE="${GITHUB_API_URL:-https://api.github.com}"
PR_NUMBER="${GITHUB_EVENT_PULL_REQUEST_NUMBER:-}"
REPO="${GITHUB_REPOSITORY:-}"
PLATFORM="github"
echo "Platform: GitHub"
fi
# Resolve PR number from the event payload.
PR_NUMBER=""
if [ -n "${GITHUB_EVENT_PATH:-}" ] && [ -f "${GITHUB_EVENT_PATH}" ]; then
PR_NUMBER=$(node -e "
try {
const e = require(process.env.GITHUB_EVENT_PATH);
const n = (e.pull_request && e.pull_request.number) || e.number || '';
process.stdout.write(String(n || ''));
} catch { process.stdout.write(''); }
")
fi
echo "Repo: ${REPO}, PR: ${PR_NUMBER}"
echo "DEBUG: PLATFORM=${PLATFORM} API_BASE=${API_BASE} EVENT=${GITHUB_EVENT_PATH:-}"
if [ -z "$PR_NUMBER" ]; then
echo "Not a pull request event. Skipping review."
@@ -109,55 +133,45 @@ const apiBase = '${API_BASE}';
const repo = '${REPO}';
const prNumber = '${PR_NUMBER}';
const token = '${PI_TOKEN}';
const platform = '${PLATFORM}';
const maxBytes = ${PI_MAX_DIFF:-80000};
function fetchDiff() {
return new Promise((resolve, reject) => {
// Try Gitea diff endpoint first
const giteaPath = '/repos/' + repo + '/pulls/' + prNumber + '.diff';
const githubPath = '/repos/' + repo + '/pulls/' + prNumber;
// Gitea: GET {api}/repos/{owner}/{repo}/pulls/{n}.diff
// GitHub: GET {api}/repos/{owner}/{repo}/pulls/{n} with Accept: application/vnd.github.v3.diff
const path = platform === 'gitea'
? '/repos/' + repo + '/pulls/' + prNumber + '.diff'
: '/repos/' + repo + '/pulls/' + prNumber;
const url = new URL(apiBase + giteaPath);
const url = new URL(apiBase + path);
const transport = url.protocol === 'http:' ? http : https;
const headers = {
'Authorization': 'token ' + token,
'User-Agent': 'pi-code-review',
'Accept': platform === 'gitea' ? 'text/plain' : 'application/vnd.github.v3.diff',
};
const options = {
hostname: url.hostname,
port: url.port || (url.protocol === 'http:' ? 80 : 443),
path: url.pathname,
method: 'GET',
headers: {
'Authorization': 'token ' + token,
'Accept': 'text/plain',
},
headers,
};
const req = transport.request(options, (res) => {
if (res.statusCode === 404 && apiBase.indexOf('github.com') !== -1) {
// Fallback to GitHub diff format
reject(new Error('GitHub fallback not implemented'));
return;
}
if (res.statusCode < 200 || res.statusCode >= 300) {
let body = '';
res.on('data', (c) => { body += c; });
res.on('end', () => { reject(new Error('API ' + res.statusCode + ': ' + body.slice(0, 200))); });
res.on('end', () => { reject(new Error('API ' + res.statusCode + ' for ' + url.href + ': ' + body.slice(0, 200))); });
return;
}
let data = '';
let bytes = 0;
res.on('data', (chunk) => {
bytes += chunk.length;
if (maxBytes > 0 && bytes <= maxBytes) {
data += chunk;
}
});
res.on('end', () => {
if (maxBytes > 0 && data.length >= maxBytes) {
data = data.slice(0, maxBytes) + '\\n... (truncated at ' + maxBytes + ' bytes)';
}
resolve(data);
});
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => { resolve(data); });
});
req.on('error', (e) => { reject(e); });
req.end();
@@ -302,17 +316,7 @@ echo "::endgroup::"
# ─── Phase 4: Post comment ────────────────────────────────────────────────────
echo "::group::Post review comment"
# Detect Gitea vs GitHub
if [ -n "${GITEA_SERVER_URL:-}" ]; then
API_BASE="${GITEA_SERVER_URL}/api/v1"
PR_NUMBER="${GITEA_EVENT_PULL_REQUEST_NUMBER:-}"
REPO="${GITEA_REPOSITORY:-}"
else
API_BASE="${GITHUB_API_URL:-https://api.github.com}"
PR_NUMBER="${GITHUB_EVENT_PULL_REQUEST_NUMBER:-}"
REPO="${GITHUB_REPOSITORY:-}"
fi
# API_BASE / REPO / PR_NUMBER were resolved in Phase 2.
if [ -z "$PR_NUMBER" ]; then
echo "Not a pull request event. Review written to /tmp/pi-review.md only."
echo "::endgroup::"