Files
docs/update_api_docs.sh
T
Lunny Xiao bc795ac24a Fix the swagger update cron job (#481)
The scheduled `update swagger files` job has failed on **every** run since it was added (I checked the run list on gitea.com, ~250 consecutive failures). Two reasons:

1. Upstream moved the file: `go-gitea/gitea` main no longer has `templates/swagger/v1_json.tmpl`, it is now `templates/swagger/v1-swagger.generated.json`, and the placeholders changed from `{{.SwaggerAppVer}}` / `{{.SwaggerAppSubUrl}}` to `0.0.0+GITEA-API-APP-VERSION` / `/GITEA-API-APP-SUBURL/api/v1`. Because the script used `curl --silent` without `--fail`, the 404 body was written into `static/swagger-latest.json`.
2. `main` is protected (`required_approvals=1`), so the job's `git push` to main could never succeed.

Changes:

- `update_api_docs.sh`: `set -euo pipefail`, download with `--fail` (a broken download now aborts instead of committing garbage), try the new generated json first and fall back to the old template for released tags, handle the 1.28+/1.24+/<1.24 placeholder variants, and add a `--latest-only` flag.
- `Makefile`: new `update-api-docs-latest` target for the cron job; `clean` no longer deletes the committed `static/swagger-*.json` files (deleting them breaks `make build`).
- `.gitea/workflows/update_swagger.yaml`: every 12h (plus `workflow_dispatch`) it regenerates only `static/swagger-latest.json`, verifies no placeholder is left and the file is valid JSON, force pushes to `bot/update-swagger-latest` and opens a pull request via the API (HTTP 409 = a PR is already open, it just now points at the new commit). It skips entirely when the bot branch already carries the same file, so no PR churn.
- `README.md`: document the two make targets and the automation.

`secrets.DEPLOY_TOKEN` must belong to a real user with `write:repository` so the PR checks are triggered; the job fails with a clear message if it is empty.

Tested locally in a scratch clone: `make update-api-docs-latest` produces a valid `dev` spec with no placeholders left, `make update-api-docs` still regenerates all released versions, and the workflow shell logic was simulated against a local bare repo for all three paths (open PR / bot branch already up to date / main already up to date), including a shallow clone to confirm `fetch-depth: 1` force pushes work.

Fixes #454

Reviewed-on: https://gitea.com/gitea/docs/pulls/481
Reviewed-by: techknowlogick <[email protected]>
2026-08-02 23:25:17 +00:00

86 lines
2.5 KiB
Bash
Executable File

#!/bin/bash
#
# Regenerates the swagger definitions served by this site.
#
# Usage: ./update_api_docs.sh [--latest-only] [sed -i suffix] [extra sed args...]
#
# --latest-only only refresh static/swagger-latest.json from gitea main,
# leaving the released static/swagger-<minor>.json untouched.
set -euo pipefail
LATEST_ONLY=0
if [ "${1:-}" = "--latest-only" ]; then
LATEST_ONLY=1
shift
fi
SED_INPLACE=(-i)
EXTRA_SED_ARGS=()
if [ "$#" -gt 0 ]; then
SED_INPLACE=(-i "$1")
shift
else
if sed --version >/dev/null 2>&1; then
SED_INPLACE=(-i)
else
SED_INPLACE=(-i '')
fi
fi
EXTRA_SED_ARGS=("$@")
inplace_sed() {
# ${arr[@]+...} keeps `set -u` happy with empty arrays on bash 3.2 (macOS)
sed "${SED_INPLACE[@]}" ${EXTRA_SED_ARGS[@]+"${EXTRA_SED_ARGS[@]}"} "$@"
}
# gitea >= 1.28 ships a pre-generated json, older versions ship a go template
SWAGGER_PATHS=(
'templates/swagger/v1-swagger.generated.json'
'templates/swagger/v1_json.tmpl'
)
# download_swagger <git ref> <output file>
download_swagger() {
local ref="$1" output="$2" path
for path in "${SWAGGER_PATHS[@]}"; do
if curl --silent --fail --location --output "$output" \
"https://raw.githubusercontent.com/go-gitea/gitea/${ref}/${path}"; then
return 0
fi
done
echo "unable to download the swagger definition of ${ref}" >&2
return 1
}
# rewrite_swagger <file> <version to display>
rewrite_swagger() {
local file="$1" version="$2"
# gitea >= 1.28
inplace_sed "s|\"version\": \"0.0.0+GITEA-API-APP-VERSION\"|\"version\": \"${version}\"|" "$file"
inplace_sed 's|"basePath": "/GITEA-API-APP-SUBURL/api/v1"|"basePath": "https://gitea.com/api/v1"|' "$file"
# gitea >= 1.24
inplace_sed "s|\"version\": \"{{.SwaggerAppVer}}\"|\"version\": \"${version}\"|" "$file"
inplace_sed 's|"basePath": "{{.SwaggerAppSubUrl}}/api/v1"|"basePath": "https://gitea.com/api/v1"|' "$file"
# gitea < 1.24
inplace_sed "s|\"version\": \"{{AppVer \| JSEscape}}\"|\"version\": \"${version}\"|" "$file"
inplace_sed "s#\"basePath\": \"{{AppSubUrl | JSEscape}}/api/v1\"#\"basePath\": \"https://gitea.com/api/v1\"#" "$file"
}
download_swagger 'refs/heads/main' v1_json.tmpl
rewrite_swagger v1_json.tmpl 'dev'
mv v1_json.tmpl static/swagger-latest.json
if [ "$LATEST_ONLY" -eq 1 ]; then
exit 0
fi
for ver in '1.27.1' '1.26.4' '1.25.5' '1.24.7' '1.23.8' '1.22.6'; do
download_swagger "refs/tags/v${ver}" v1_json.tmpl
rewrite_swagger v1_json.tmpl "${ver}"
minor=$(echo "$ver" | cut -d '.' -f 2)
mv v1_json.tmpl "static/swagger-$minor.json"
done