diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..83b3823b --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,98 @@ +name: build +run-name: Check Mapache service builds + +# Aggregates the six per-service image builds into one check so branch +# protection has a single required status to gate on. +# +# Only the image builds are waited on. mapache-go / mapache-py run on +# `push: branches: [main]` with path filters, so they never run for a +# feature branch push and waiting on them would hang until timeout. +# +# Tags are filtered to v* to match the service workflows. The library +# tags (mapache-py/*, mapache-go/*) don't trigger an image build, so a +# broader filter here would wait on runs that never start. + +on: + push: + branches: + - "**" + tags: + - "v*" + workflow_dispatch: + inputs: + sha: + description: Commit SHA to check. Defaults to main. + required: false + type: string + +permissions: + actions: read + contents: read + +jobs: + build: + runs-on: ubuntu-latest + name: Build + steps: + - name: Check workflow results + env: + GH_TOKEN: ${{ github.token }} + REPO: ${{ github.repository }} + INPUT_SHA: ${{ inputs.sha }} + CURRENT_SHA: ${{ github.sha }} + run: | + set -euo pipefail + + sha="$INPUT_SHA" + if [ -z "$sha" ]; then + sha="$CURRENT_SHA" + fi + if [ -z "$sha" ]; then + sha="$(gh api "repos/$REPO/branches/main" --jq '.commit.sha')" + fi + + wait_for_workflow() { + local label="$1" + local workflow="$2" + local result="" + + for attempt in $(seq 1 90); do + result="$( + gh api --method GET "repos/$REPO/actions/workflows/$workflow/runs" \ + -f head_sha="$sha" \ + -f per_page=1 \ + --jq '(.workflow_runs[0] // empty) | [.status, (.conclusion // ""), .html_url] | @tsv' + )" + + if [ -n "$result" ]; then + local status conclusion url + IFS=$'\t' read -r status conclusion url <<< "$result" + echo "$label: $status ${conclusion:-pending} $url" + + if [ "$status" = "completed" ]; then + if [ "$conclusion" = "success" ]; then + return 0 + fi + + echo "$label failed with conclusion: $conclusion" + return 1 + fi + else + echo "$label: waiting for workflow run for $sha" + fi + + if [ "$attempt" -eq 90 ]; then + echo "$label did not complete for $sha before timeout" + return 1 + fi + + sleep 10 + done + } + + wait_for_workflow "auth" "auth.yml" + wait_for_workflow "vehicle" "vehicle.yml" + wait_for_workflow "gr26" "gr26.yml" + wait_for_workflow "live" "live.yml" + wait_for_workflow "query" "query.yml" + wait_for_workflow "dashboard" "dashboard.yml" diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ed0b8c96..76718409 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,7 +14,9 @@ on: env: INFRA_REPO: Gaucho-Racing/infrastructure - KUSTOMIZATION: infra/kubernetes/manifests/mapache/kustomization.yaml + # Path within the infrastructure repo, which is checked out into ./infra — + # prefix with infra/ for filesystem access, use bare for `git -C infra`. + KUSTOMIZATION: kubernetes/gr-foundry/manifests/mapache/kustomization.yaml SERVICES: "auth vehicle gr26 live query dashboard" jobs: @@ -44,7 +46,7 @@ jobs: run: | NEW_TAG="${{ github.event.release.tag_name }}" NEW="${NEW_TAG#v}" - OLD="$(yq '.images[] | select(.name == "ghcr.io/gaucho-racing/mapache/auth") | .newTag' "$KUSTOMIZATION")" + OLD="$(yq '.images[] | select(.name == "ghcr.io/gaucho-racing/mapache/auth") | .newTag' "infra/$KUSTOMIZATION")" echo "new_tag=$NEW_TAG" >> "$GITHUB_OUTPUT" echo "new=$NEW" >> "$GITHUB_OUTPUT" echo "old=$OLD" >> "$GITHUB_OUTPUT" @@ -68,9 +70,9 @@ jobs: $0 ~ "- name: ghcr.io/gaucho-racing/mapache/(auth|vehicle|gr26|live|query|dashboard)$" { inmap=1; print; next } inmap==1 && $1=="newTag:" { sub(/newTag:[[:space:]]*.*/, "newTag: " new); inmap=0 } { print } - ' "$KUSTOMIZATION" > "$KUSTOMIZATION.tmp" && mv "$KUSTOMIZATION.tmp" "$KUSTOMIZATION" + ' "infra/$KUSTOMIZATION" > "infra/$KUSTOMIZATION.tmp" && mv "infra/$KUSTOMIZATION.tmp" "infra/$KUSTOMIZATION" echo "--- diff ---" - git -C infra diff -- kubernetes/manifests/mapache/kustomization.yaml + git -C infra diff -- "$KUSTOMIZATION" - name: Build changelog if: steps.versions.outputs.skip == 'false' diff --git a/auth/config/config.go b/auth/config/config.go index 7415c227..a8cbb2fe 100644 --- a/auth/config/config.go +++ b/auth/config/config.go @@ -66,7 +66,7 @@ var Sentinel = struct { // SentinelIssuer is the iss claim Sentinel v5 stamps into every signed // token. Must byte-match SENTINEL_URL — the issuer is fixed in v5 to // the public base URL. -const SentinelIssuer = "https://sentinel-v5.gauchoracing.com" +const SentinelIssuer = "https://sso.gauchoracing.com" func IsProduction() bool { return Env == "PROD" diff --git a/dashboard/src/components/Header.tsx b/dashboard/src/components/Header.tsx index 3ca6ce1b..5024fac4 100644 --- a/dashboard/src/components/Header.tsx +++ b/dashboard/src/components/Header.tsx @@ -53,7 +53,7 @@ const Header = (props: HeaderProps) => { window.open( - "https://sentinel-v5.gauchoracing.com/settings", + "https://sso.gauchoracing.com/settings", "_blank", ) } diff --git a/dashboard/src/consts/config.tsx b/dashboard/src/consts/config.tsx index 20ea8ad8..cd714c6e 100644 --- a/dashboard/src/consts/config.tsx +++ b/dashboard/src/consts/config.tsx @@ -5,7 +5,7 @@ export const BACKEND_WS_URL = import.meta.env.VITE_BACKEND_WS_URL ?? "wss://mapache.gauchoracing.com/api"; export const SENTINEL_OAUTH_BASE_URL = - "https://sentinel-v5.gauchoracing.com/oauth/authorize"; + "https://sso.gauchoracing.com/oauth/authorize"; export const SENTINEL_CLIENT_ID = import.meta.env.VITE_SENTINEL_CLIENT_ID ?? "TIvD6jCH3mGV"; diff --git a/query/query/config/config.py b/query/query/config/config.py index 595a2189..2ca58627 100644 --- a/query/query/config/config.py +++ b/query/query/config/config.py @@ -35,7 +35,7 @@ class Config: SKIP_AUTH_CHECK: bool = os.getenv('SKIP_AUTH_CHECK', 'false').lower() == 'true' SENTINEL_URL: str = os.getenv('SENTINEL_URL') SENTINEL_CLIENT_ID: str = os.getenv('SENTINEL_CLIENT_ID') - SENTINEL_ISSUER: str = 'https://sentinel-v5.gauchoracing.com' + SENTINEL_ISSUER: str = 'https://sso.gauchoracing.com' @staticmethod def get_database_url() -> URL: