diff --git a/.github/workflows/build-linux-amd64.yml b/.github/workflows/build-linux-amd64.yml index 6a3bffa..4d06cca 100644 --- a/.github/workflows/build-linux-amd64.yml +++ b/.github/workflows/build-linux-amd64.yml @@ -53,6 +53,58 @@ jobs: apt-get install -y --no-install-recommends \ build-essential cmake ninja-build python3 python3-venv pkg-config \ libssl-dev curl git ca-certificates + - name: Preflight Gitea upload (fast-fail) + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} + run: | + set -euo pipefail + : "${GITEA_TOKEN:?GITEA_TOKEN secret is required}" + server="${GITHUB_SERVER_URL:-${{ github.server_url }}}" + owner="${GITHUB_REPOSITORY_OWNER:-${{ github.repository_owner }}}" + repo_full="${GITHUB_REPOSITORY:-${{ github.repository }}}" + pkg="${repo_full##*/}-preflight" + version="preflight-${GITHUB_RUN_ID:-0}-${GITHUB_RUN_ATTEMPT:-0}-$(date +%s)" + name="check.bin" + tmpfile="$(mktemp)" + printf "auth check %s\n" "$(date -u +%FT%TZ)" > "$tmpfile" + url="$server/api/packages/$owner/generic/$pkg/$version/$name?replace=1" + mask() { local s="$1"; local n=${#s}; if [ "$n" -le 8 ]; then printf "*** (len=%s)" "$n"; else printf "%s***%s (len=%s)" "${s:0:4}" "${s:n-4:4}" "$n"; fi; } + echo "Preflight variables:" + echo " server=$server" + echo " owner=$owner" + echo " package=$pkg" + echo " version=$version" + echo " url=$url" + echo " token=$(mask "$GITEA_TOKEN")" + echo "Validating token via /api/v1/user:" + curl -sS -o /dev/null -w " auth check -> HTTP %{http_code}\n" \ + -H "Authorization: token ${GITEA_TOKEN}" "$server/api/v1/user" || true + echo "Attempting preflight upload" + http_code=$(curl -sS -i -X PUT \ + -H "Authorization: token ${GITEA_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + --upload-file "$tmpfile" "$url" \ + -o /dev/null -w "%{http_code}" || true) + if [ "$http_code" = "401" ]; then + echo "401 Unauthorized with token header; retrying with HTTP Basic auth (owner:token)" + http_code=$(curl -sS -i -X PUT \ + -u "$owner:${GITEA_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + --upload-file "$tmpfile" "$url" \ + -o /dev/null -w "%{http_code}" || true) + fi + echo "Preflight HTTP $http_code" + case "$http_code" in + 2*) echo "Preflight upload succeeded, cleaning up" ;; + *) echo "Preflight upload failed with HTTP $http_code" >&2; exit 1 ;; + esac + # Cleanup the uploaded dummy package version (best effort) + curl -sS -o /dev/null -w " delete -> HTTP %{http_code}\n" \ + -H "Authorization: token ${GITEA_TOKEN}" -X DELETE \ + "$server/api/packages/$owner/generic/$pkg/$version" || \ + curl -sS -o /dev/null -w " delete (basic) -> HTTP %{http_code}\n" \ + -u "$owner:${GITEA_TOKEN}" -X DELETE \ + "$server/api/packages/$owner/generic/$pkg/$version" || true - name: Initialize submodules run: | set -e @@ -129,9 +181,62 @@ jobs: [ -n "$file" ] || { echo "file not set" >&2; exit 1; } name="$(basename "$file")" url="$server/api/packages/$owner/generic/$pkg/$version/$name?replace=1" + # Debug helpers (avoid leaking secrets) + mask() { local s="$1"; local n=${#s}; if [ "$n" -le 8 ]; then printf "*** (len=%s)" "$n"; else printf "%s***%s (len=%s)" "${s:0:4}" "${s:n-4:4}" "$n"; fi; } + filesize=$(stat -c%s "$file" 2>/dev/null || echo "?") + host="$(echo "$server" | sed -E 's#^https?://([^/]+).*#\1#')" + echo "Derived variables:" + echo " server=$server" + echo " owner=$owner" + echo " package=$pkg" + echo " version=$version" + echo " artifact=$file (size=${filesize} bytes, name=$name)" + echo " url=$url" + echo " token=$(mask "$GITEA_TOKEN")" + echo "Curl version:"; curl --version | head -n 1 + echo "DNS for $host:"; getent hosts "$host" || true + + echo "Checking API reachability (no auth):" + curl -sS -o /dev/null -w " /api/v1/version -> HTTP %{http_code}\n" "$server/api/v1/version" || true + + echo "Validating token via /api/v1/user:" + curl -sS -o /dev/null -w " auth check -> HTTP %{http_code}\n" \ + -H "Authorization: token ${GITEA_TOKEN}" "$server/api/v1/user" || true + echo "Uploading $file to $url" - curl -fsSL -X PUT \ + # Perform upload and capture response details without exposing token + tmpdir="$(mktemp -d)" + resp_headers="$tmpdir/headers.txt" + resp_body="$tmpdir/body.txt" + http_code=$(curl -sS -i -X PUT \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/octet-stream" \ - --upload-file "$file" "$url" - echo "Upload complete." \ No newline at end of file + --retry 2 --retry-delay 2 --max-time 300 \ + --upload-file "$file" "$url" \ + -D "$resp_headers" -o "$resp_body" -w "%{http_code}" || true) + echo "Response HTTP code: $http_code" + echo "Response headers:"; sed -n '1,200p' "$resp_headers" | sed 's/\r$//' || true + if [ -s "$resp_body" ]; then + echo "Response body (first 200 bytes):"; head -c 200 "$resp_body"; echo + fi + + # If unauthorized, retry once using HTTP Basic auth (per Gitea docs) + if [ "$http_code" = "401" ]; then + echo "401 Unauthorized with token header; retrying with HTTP Basic auth (owner:token)" + http_code=$(curl -sS -i -X PUT \ + -u "$owner:${GITEA_TOKEN}" \ + -H "Content-Type: application/octet-stream" \ + --retry 2 --retry-delay 2 --max-time 300 \ + --upload-file "$file" "$url" \ + -D "$resp_headers" -o "$resp_body" -w "%{http_code}" || true) + echo "Retry HTTP code: $http_code" + echo "Retry response headers:"; sed -n '1,200p' "$resp_headers" | sed 's/\r$//' || true + if [ -s "$resp_body" ]; then + echo "Retry response body (first 200 bytes):"; head -c 200 "$resp_body"; echo + fi + fi + + case "$http_code" in + 2*) echo "Upload complete." ;; + *) echo "Upload failed with HTTP $http_code" >&2; exit 1 ;; + esac \ No newline at end of file