CI: forge injects CI_REGISTRY built-in var (GITGUD_REGISTRY_HOST)
7370f38 · gmorell · 2026-06-25 18:17
Message
{commit_body(@commit)}
Files changed
modified
.forgejo/workflows/build.yml
+5
−5
@@ -18,16 +18,16 @@ jobs:
| 18 | 18 | # endpoint but login-action requires it to be non-empty. |
| 19 | 19 | - uses: docker/login-action@v3 |
| 20 | 20 | with: |
| 21 | − registry: ggr.neiam.co | |
| 21 | + registry: ${{ vars.CI_REGISTRY }} | |
| 22 | 22 | username: gitgud-actions |
| 23 | 23 | password: ${{ github.token }} |
| 24 | 24 | |
| 25 | 25 | - uses: docker/metadata-action@v5 |
| 26 | 26 | id: meta |
| 27 | 27 | with: |
| 28 | − # Push to the job's OWN repo path (ggr.neiam.co/<owner>/<repo>); | |
| 28 | + # Push to the job's OWN repo path (${{ vars.CI_REGISTRY }}/<owner>/<repo>); | |
| 29 | 29 | # the per-job token only grants push there. |
| 30 | − images: ggr.neiam.co/${{ github.repository }} | |
| 30 | + images: ${{ vars.CI_REGISTRY }}/${{ github.repository }} | |
| 31 | 31 | tags: | |
| 32 | 32 | type=sha,format=long |
| 33 | 33 | type=ref,event=branch |
@@ -40,5 +40,5 @@ jobs:
| 40 | 40 | push: true |
| 41 | 41 | tags: ${{ steps.meta.outputs.tags }} |
| 42 | 42 | labels: ${{ steps.meta.outputs.labels }} |
| 43 | − cache-from: type=registry,ref=ggr.neiam.co/${{ github.repository }}:buildcache | |
| 44 | − cache-to: type=registry,ref=ggr.neiam.co/${{ github.repository }}:buildcache,mode=max | |
| 43 | + cache-from: type=registry,ref=${{ vars.CI_REGISTRY }}/${{ github.repository }}:buildcache | |
| 44 | + cache-to: type=registry,ref=${{ vars.CI_REGISTRY }}/${{ github.repository }}:buildcache,mode=max |
modified
config/config.exs
+7
−0
@@ -85,6 +85,13 @@ config :git_gud, GitGud.Packages.Token,
| 85 | 85 | ttl_seconds: 300, |
| 86 | 86 | private_key_pem: nil |
| 87 | 87 | |
| 88 | +# Bundled OCI registry host (zot). When set, every CI job receives it as | |
| 89 | +# the built-in variable `vars.CI_REGISTRY` so workflows can | |
| 90 | +# `docker login`/push without per-repo config. Wired from | |
| 91 | +# GITGUD_REGISTRY_HOST in runtime.exs; nil = not injected (workflows must | |
| 92 | +# supply their own registry). | |
| 93 | +config :git_gud, :registry_host, nil | |
| 94 | + | |
| 88 | 95 | config :git_gud, GitGud.Workflows.Workers.CacheEviction, |
| 89 | 96 | # Drop entries with `last_used_at` (or `archived_at` when never read) |
| 90 | 97 | # older than this many days. |
modified
config/runtime.exs
+7
−0
@@ -135,6 +135,13 @@ if config_env() == :prod do
| 135 | 135 | config :git_gud, GitGud.Packages.Token, private_key_pem: pem |
| 136 | 136 | end |
| 137 | 137 | |
| 138 | + # Registry host injected into CI jobs as `vars.CI_REGISTRY` (e.g. | |
| 139 | + # "ggr.neiam.co") so workflows reference ${{ vars.CI_REGISTRY }} | |
| 140 | + # without hardcoding or per-repo config. | |
| 141 | + if host = System.get_env("GITGUD_REGISTRY_HOST") do | |
| 142 | + config :git_gud, :registry_host, host | |
| 143 | + end | |
| 144 | + | |
| 138 | 145 | # zot → Packages mirror webhook shared secret. zot sends it as |
| 139 | 146 | # `Authorization: Bearer <secret>`; `PackagesWebhookController` |
| 140 | 147 | # secure-compares against this value. Unset = no auth (open |
modified
lib/git_gud_web/controllers/runner_controller.ex
+14
−0
@@ -197,6 +197,9 @@ defmodule GitGudWeb.RunnerController do
| 197 | 197 | |> GitGud.Repo.preload([:owner, :organization]) |
| 198 | 198 | |
| 199 | 199 | {secrets, vars} = GitGud.Secrets.resolve_for(repo) |
| 200 | + # System-provided built-in vars (e.g. CI_REGISTRY) as defaults; | |
| 201 | + # user-defined org/repo vars override them. | |
| 202 | + vars = Map.merge(builtin_vars(), vars) | |
| 200 | 203 | token = GitGud.Workflows.RunnerJwt.mint(job, run) |
| 201 | 204 | |
| 202 | 205 | %TaskMsg{ |
@@ -212,6 +215,17 @@ defmodule GitGudWeb.RunnerController do
| 212 | 215 | } |
| 213 | 216 | end |
| 214 | 217 | |
| 218 | + # Built-in CI variables the forge injects into every job. CI_REGISTRY | |
| 219 | + # is the bundled OCI registry host (config :git_gud, :registry_host, | |
| 220 | + # from GITGUD_REGISTRY_HOST) so workflows can `docker login`/push | |
| 221 | + # without per-repo config. nil host → not injected. | |
| 222 | + defp builtin_vars do | |
| 223 | + case Application.get_env(:git_gud, :registry_host) do | |
| 224 | + host when is_binary(host) and host != "" -> %{"CI_REGISTRY" => host} | |
| 225 | + _ -> %{} | |
| 226 | + end | |
| 227 | + end | |
| 228 | + | |
| 215 | 229 | defp build_needs(%GitGud.Workflows.WorkflowJob{needs: []}), do: %{} |
| 216 | 230 | |
| 217 | 231 | defp build_needs(%GitGud.Workflows.WorkflowJob{workflow_run_id: rid, needs: needs}) do |
Parents: 6fbf08e