Commit dd5353fa authored by xuwang's avatar xuwang
Browse files

fix(renovate): normalize endpoint scheme; add RENOVATE_TOKEN_FILE for multi-server repos



More issues found validating against som-irt-services (a two-server project:
gitlab.med code repo + code.stanford.edu Terraform backend):

- GITLAB_SERVER follows OTICA's bare-host convention (gitlab-server.sh emits no
  scheme), so the endpoint came out as "host/api/v4" and Renovate rejected it.
  Normalize GITLAB_SERVER and RENOVATE_ENDPOINT to include https://.
- The project's GITLAB_TOKEN targeted code.stanford.edu (TF backend) while the
  repo lives on gitlab.med, so Renovate authenticated with the wrong token. Add
  RENOVATE_TOKEN_FILE (precedence RENOVATE_TOKEN > RENOVATE_TOKEN_FILE >
  GITLAB_TOKEN > ~/.gitlab-token) so Renovate can use a token for the repo's own
  server, and scrub it from Renovate's env. Document the multi-server case.

Changelog: fixed
Co-Authored-By: default avatarClaude Opus 4.8 <noreply@anthropic.com>
parent 5248d486
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -82,8 +82,9 @@ Override with `RENOVATE_CMD` (e.g. `RENOVATE_CMD="npx --yes renovate"`, a custom
docker wrapper, or `RENOVATE_CMD=echo` to print the assembled command without
running it).

**Token.** Renovate authenticates with the consumer's GitLab token, resolved
like the rest of OTICA: `RENOVATE_TOKEN``GITLAB_TOKEN``~/.gitlab-token`.
**Token.** Renovate authenticates with a GitLab token for **the repo's own
server**, resolved by precedence:
`RENOVATE_TOKEN``RENOVATE_TOKEN_FILE``GITLAB_TOKEN``~/.gitlab-token`.
Scope depends on the action:

| Action | Required token scope |
@@ -92,8 +93,15 @@ Scope depends on the action:
| `renovate-dryrun`, `renovate-admin-dryrun` | `read_api` |
| `renovate-run`, `renovate-admin-run` | `api` (+ Developer role to open MRs) |

The endpoint defaults to `${GITLAB_SERVER}/api/v4` (`GITLAB_SERVER` defaults to
`https://code.stanford.edu`).
> **Multi-server projects.** A project's `GITLAB_TOKEN` may target a *different*
> GitLab than where the code lives — e.g. a `code.stanford.edu` Terraform backend
> while the repo is on `gitlab.med`. Renovate needs a token for the **repo's**
> server, so set `RENOVATE_TOKEN_FILE` (or `RENOVATE_TOKEN`) to that token; it
> takes precedence over the ambient `GITLAB_TOKEN`.

The endpoint is derived from the repo's git remote host (e.g.
`https://gitlab.med.stanford.edu/api/v4`); `GITLAB_SERVER` / `RENOVATE_ENDPOINT`
override it, and a bare host is normalized to `https://`.

## Project targets (`renovate.mk`)

@@ -124,9 +132,10 @@ make renovate-run # open the MRs (needs api token; prompts to confirm)
| --- | --- | --- |
| `RENOVATE_CMD` | _(auto)_ | Force a specific runtime |
| `RENOVATE_PLATFORM` | `gitlab` | Renovate platform |
| `RENOVATE_ENDPOINT` | `${GITLAB_SERVER}/api/v4` | GitLab API endpoint |
| `RENOVATE_ENDPOINT` | _(derived from remote host)_ | GitLab API endpoint |
| `RENOVATE_CONFIG` | `renovate.json` | Config file for `renovate-validate` / `renovate-init` |
| `RENOVATE_REPO` | _(derived from git remote)_ | `namespace/project` to operate on |
| `RENOVATE_TOKEN_FILE` | _(empty)_ | File holding the repo-server token (wins over `GITLAB_TOKEN`) |
| `RENOVATE_ARGS` | _(empty)_ | Extra args appended to the Renovate invocation |

The starter `renovate.json` extends `config:recommended` with a dependency
+5 −1
Original line number Diff line number Diff line
@@ -31,9 +31,13 @@ RENOVATE_ENDPOINT ?=
RENOVATE_CONFIG    ?= renovate.json
RENOVATE_REPO      ?=
RENOVATE_ARGS      ?=
# Dedicated token file for the repo's server. Set this when the project's
# GITLAB_TOKEN points at a different GitLab (e.g. a code.stanford.edu Terraform
# backend) than where this repo lives.
RENOVATE_TOKEN_FILE ?=

export RENOVATE_CMD RENOVATE_PLATFORM RENOVATE_ENDPOINT \
       RENOVATE_CONFIG RENOVATE_REPO RENOVATE_ARGS
       RENOVATE_CONFIG RENOVATE_REPO RENOVATE_ARGS RENOVATE_TOKEN_FILE

.PHONY: renovate-check
renovate-check: ## verify a Renovate runtime is available (renovate | npx | docker)
+19 −3
Original line number Diff line number Diff line
@@ -16,8 +16,11 @@
#   RENOVATE_ARGS         extra args appended to the Renovate invocation
#   RENOVATE_AUTODISCOVER_FILTER  optional autodiscover glob (autodiscover modes)
#   RENOVATE_DOCKER_IMAGE default: renovate/renovate
#   RENOVATE_TOKEN        GitLab token (default: GITLAB_TOKEN / ~/.gitlab-token)
#                         scope: 'api' for real runs, 'read_api' for dry-runs
#   RENOVATE_TOKEN        GitLab token for the repo's server (scope: 'api' real,
#                         'read_api' dry-run). Precedence:
#                         RENOVATE_TOKEN > RENOVATE_TOKEN_FILE > GITLAB_TOKEN > ~/.gitlab-token
#   RENOVATE_TOKEN_FILE   file holding that token; use when the project's
#                         GITLAB_TOKEN targets a different server than this repo
#   GITLAB_SERVER         default: the origin remote's host (else code.stanford.edu)
#   GITLAB_TOKEN[_FILE]   consumer GitLab token / file (default ~/.gitlab-token)
#
@@ -64,6 +67,18 @@ if [ -z "${GITLAB_SERVER}" ]; then
    GITLAB_SERVER="${_host:+https://${_host}}"
    GITLAB_SERVER="${GITLAB_SERVER:-https://code.stanford.edu}"
fi
# OTICA's GITLAB_SERVER convention (gitlab-server.sh) is a bare host with no
# scheme; Renovate requires a full URL, so ensure one is present.
case "${GITLAB_SERVER}" in *://*) ;; *) GITLAB_SERVER="https://${GITLAB_SERVER}" ;; esac
# Token precedence: RENOVATE_TOKEN > RENOVATE_TOKEN_FILE > GITLAB_TOKEN > ~/.gitlab-token.
# A project's GITLAB_TOKEN may target a DIFFERENT GitLab server than this repo
# (e.g. a code.stanford.edu Terraform backend while the code lives on gitlab.med),
# so a dedicated RENOVATE_TOKEN[_FILE] for the repo's own server wins over it.
RENOVATE_TOKEN="${RENOVATE_TOKEN:-}"
RENOVATE_TOKEN_FILE="${RENOVATE_TOKEN_FILE:-}"
if [ -z "${RENOVATE_TOKEN}" ] && [ -n "${RENOVATE_TOKEN_FILE}" ] && [ -f "${RENOVATE_TOKEN_FILE}" ]; then
    RENOVATE_TOKEN="$(cat "${RENOVATE_TOKEN_FILE}")"
fi
GITLAB_TOKEN_FILE="${GITLAB_TOKEN_FILE:-${HOME}/.gitlab-token}"
GITLAB_TOKEN="${GITLAB_TOKEN:-}"
if [ -z "${GITLAB_TOKEN}" ] && [ -f "${GITLAB_TOKEN_FILE}" ]; then
@@ -71,6 +86,7 @@ if [ -z "${GITLAB_TOKEN}" ] && [ -f "${GITLAB_TOKEN_FILE}" ]; then
fi
RENOVATE_TOKEN="${RENOVATE_TOKEN:-${GITLAB_TOKEN}}"
RENOVATE_ENDPOINT="${RENOVATE_ENDPOINT:-${GITLAB_SERVER%/}/api/v4}"
case "${RENOVATE_ENDPOINT}" in *://*) ;; *) RENOVATE_ENDPOINT="https://${RENOVATE_ENDPOINT}" ;; esac

require_token() {   # require_token <scope>
    [ -n "${RENOVATE_TOKEN}" ] || err \
@@ -92,7 +108,7 @@ log_context() {
invoke() {
    (
        unset RENOVATE_CMD RENOVATE_ARGS RENOVATE_CONFIG RENOVATE_REPO \
              RENOVATE_DOCKER_IMAGE RENOVATE_AUTODISCOVER_FILTER
              RENOVATE_DOCKER_IMAGE RENOVATE_AUTODISCOVER_FILTER RENOVATE_TOKEN_FILE
        export RENOVATE_TOKEN RENOVATE_PLATFORM RENOVATE_ENDPOINT
        exec "$@"
    )