ci: derive image name + package linking from repo, add link step

Both workflows had a static IMAGE env (<owner>/<product>-docs-mcp)
and a static --package arg in the GC step. Switch both to Gitea
Actions context variables so a clone of the template into any repo
name works on the first CI run without find/replace:

  IMAGE: ${{ github.repository_owner }}/${{ github.event.repository.name }}
  --owner ${{ github.repository_owner }}
  --package ${{ github.event.repository.name }}

Also add the "Link container package to this repo" step that was
missing from the template (and which, naively copy-pasted from the
reference build, would have linked everything back to docs-mcp-
template). The new step derives owner + package + link-target all
from the running repo's context.

The github.* namespace is Gitea Actions' inherited GitHub-Actions
context — values come from the Gitea server, not github.com. Same
mechanism the reference build's $GITHUB_SHA tag-builder uses.

CLAUDE.md updated to note that image and package naming are
repo-derived; only registry endpoints and the Ollama URL need
per-clone editing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-22 09:34:26 -04:00
parent 9ba615c8ee
commit 33b0fd652e
3 changed files with 78 additions and 8 deletions
+30 -4
View File
@@ -16,7 +16,11 @@ on:
env: env:
REGISTRY_PUSH: <lan-host>:<port> REGISTRY_PUSH: <lan-host>:<port>
REGISTRY_PULL: <public-registry-hostname> REGISTRY_PULL: <public-registry-hostname>
IMAGE: <owner>/<product>-docs-mcp # Image name derives from the actual repo at runtime, so a clone
# doesn't need to find/replace anything. e.g. justin/my-product-docs.
# github.* context is Gitea Actions' inherited GitHub-Actions namespace
# — values come from the Gitea server, not github.com.
IMAGE: ${{ github.repository_owner }}/${{ github.event.repository.name }}
OLLAMA_URL: http://<gpu-host>:11434 OLLAMA_URL: http://<gpu-host>:11434
EMBED_MODEL: nomic-embed-text EMBED_MODEL: nomic-embed-text
PRODUCT_NAME: <product> PRODUCT_NAME: <product>
@@ -63,7 +67,7 @@ jobs:
run: python -m rag.index --rebuild run: python -m rag.index --rebuild
- name: Log in to registry (LAN endpoint) - name: Log in to registry (LAN endpoint)
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${REGISTRY_PUSH}" -u <user> --password-stdin run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${REGISTRY_PUSH}" -u "${{ github.repository_owner }}" --password-stdin
- name: Build & push image - name: Build & push image
run: | run: |
@@ -78,12 +82,34 @@ jobs:
docker push "${REGISTRY_PUSH}/${IMAGE}:${SHA_TAG}" docker push "${REGISTRY_PUSH}/${IMAGE}:${SHA_TAG}"
docker push "${REGISTRY_PUSH}/${IMAGE}:${DATE_TAG}" docker push "${REGISTRY_PUSH}/${IMAGE}:${DATE_TAG}"
- name: Link container package to this repo
# Gitea container packages are owned by a USER, not a repo —
# they don't auto-appear under the repo's Packages tab.
# This API call creates the association. One-time-effective:
# re-running returns 400 once linked, which we swallow.
# Endpoint requires Gitea 1.21+.
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
OWNER="${{ github.repository_owner }}"
PKG="${{ github.event.repository.name }}"
BODY=$(mktemp)
CODE=$(curl -sS -o "$BODY" -w "%{http_code}" -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
"https://${REGISTRY_PULL}/api/v1/packages/${OWNER}/container/${PKG}/-/link/${PKG}")
echo "link http=$CODE body=$(cat "$BODY")"
case "$CODE" in
201) echo "linked package to ${OWNER}/${PKG}" ;;
400) echo "already linked (re-link returns 400) — ok" ;;
*) echo "unexpected status $CODE"; exit 1 ;;
esac
- name: Prune old container versions - name: Prune old container versions
env: env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }} GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: | run: |
python scripts/registry_gc.py \ python scripts/registry_gc.py \
--owner <user> \ --owner "${{ github.repository_owner }}" \
--package <product>-docs-mcp \ --package "${{ github.event.repository.name }}" \
--keep-days 90 \ --keep-days 90 \
--keep-latest 5 --keep-latest 5
+31 -4
View File
@@ -24,7 +24,11 @@ env:
# for pulls (response bodies aren't capped). # for pulls (response bodies aren't capped).
REGISTRY_PUSH: <lan-host>:<port> REGISTRY_PUSH: <lan-host>:<port>
REGISTRY_PULL: <public-registry-hostname> REGISTRY_PULL: <public-registry-hostname>
IMAGE: <owner>/<product>-docs-mcp # Image name derives from the actual repo at runtime, so a clone
# doesn't need to find/replace anything. e.g. justin/my-product-docs.
# github.* context is Gitea Actions' inherited GitHub-Actions namespace
# — values come from the Gitea server, not github.com.
IMAGE: ${{ github.repository_owner }}/${{ github.event.repository.name }}
# Embedder. One URL per GPU; the indexer round-robins. # Embedder. One URL per GPU; the indexer round-robins.
OLLAMA_URL: http://<gpu-host>:11434 OLLAMA_URL: http://<gpu-host>:11434
@@ -126,7 +130,7 @@ jobs:
# ---- Build & push image ------------------------------------ # ---- Build & push image ------------------------------------
- name: Log in to registry (LAN endpoint) - name: Log in to registry (LAN endpoint)
if: steps.commit.outputs.changed == 'true' || inputs.force_build == true if: steps.commit.outputs.changed == 'true' || inputs.force_build == true
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${REGISTRY_PUSH}" -u <user> --password-stdin run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${REGISTRY_PUSH}" -u "${{ github.repository_owner }}" --password-stdin
- name: Build & push image - name: Build & push image
if: steps.commit.outputs.changed == 'true' || inputs.force_build == true if: steps.commit.outputs.changed == 'true' || inputs.force_build == true
@@ -145,6 +149,29 @@ jobs:
docker push "${REGISTRY_PUSH}/${IMAGE}:${SHA_TAG}" docker push "${REGISTRY_PUSH}/${IMAGE}:${SHA_TAG}"
docker push "${REGISTRY_PUSH}/${IMAGE}:${DATE_TAG}" docker push "${REGISTRY_PUSH}/${IMAGE}:${DATE_TAG}"
- name: Link container package to this repo
# Gitea container packages are owned by a USER, not a repo —
# they don't auto-appear under the repo's Packages tab.
# This API call creates the association. One-time-effective:
# re-running returns 400 once linked, which we swallow.
# Endpoint requires Gitea 1.21+.
if: steps.commit.outputs.changed == 'true' || inputs.force_build == true
env:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
OWNER="${{ github.repository_owner }}"
PKG="${{ github.event.repository.name }}"
BODY=$(mktemp)
CODE=$(curl -sS -o "$BODY" -w "%{http_code}" -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
"https://${REGISTRY_PULL}/api/v1/packages/${OWNER}/container/${PKG}/-/link/${PKG}")
echo "link http=$CODE body=$(cat "$BODY")"
case "$CODE" in
201) echo "linked package to ${OWNER}/${PKG}" ;;
400) echo "already linked (re-link returns 400) — ok" ;;
*) echo "unexpected status $CODE"; exit 1 ;;
esac
# ---- Registry GC ------------------------------------------- # ---- Registry GC -------------------------------------------
- name: Prune old container versions - name: Prune old container versions
if: steps.commit.outputs.changed == 'true' || inputs.force_build == true if: steps.commit.outputs.changed == 'true' || inputs.force_build == true
@@ -152,7 +179,7 @@ jobs:
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }} GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: | run: |
python scripts/registry_gc.py \ python scripts/registry_gc.py \
--owner <user> \ --owner "${{ github.repository_owner }}" \
--package <product>-docs-mcp \ --package "${{ github.event.repository.name }}" \
--keep-days 90 \ --keep-days 90 \
--keep-latest 5 --keep-latest 5
+17
View File
@@ -157,6 +157,23 @@ throughout. Set it on first build. References show up in:
Use lowercase, underscores not hyphens, since it ends up in tool Use lowercase, underscores not hyphens, since it ends up in tool
identifiers that the LLM reads. identifiers that the LLM reads.
### Image name and package linking are repo-name-derived
You do NOT need to edit the IMAGE env or the `--package` arg in the
workflows. Both derive from the repo at runtime via
`${{ github.repository_owner }}` and
`${{ github.event.repository.name }}`. So a clone into a repo named
`my-product-docs` automatically pushes the container as
`<owner>/my-product-docs:latest` and links the package to its own
repo. (`github.*` is Gitea Actions' inherited GitHub-Actions
namespace — the values come from the Gitea server, no github.com
involvement.)
The only workflow placeholders you still have to replace per clone
are the registry endpoints (`REGISTRY_PUSH`, `REGISTRY_PULL`) and
the Ollama URL, because those depend on the deployment environment,
not the repo identity.
## Common commands ## Common commands
```bash ```bash