name: Image rebuild (skip scrape) # Fast path for code-only changes. Skips the scrape and goes straight to: # rebuild indexes (from corpus already committed on main) + image build # + push. Runtime is ~18 min vs ~40 min for the full refresh. # # Use when a PR only changes code/config — anything where the upstream # corpus hasn't moved but we want the new Python in the running image. # # IMPORTANT: fetch-depth: 0 is required for the digest-history step # to find commits to walk. Don't change to 1. on: workflow_dispatch: env: REGISTRY_PUSH: : REGISTRY_PULL: # 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://:11434 EMBED_MODEL: nomic-embed-text PRODUCT_NAME: jobs: build: runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - name: Checkout uses: actions/checkout@v4 with: # Full history (not shallow) so the digest-history step can # walk git log up to --history-days back. fetch-depth: 0 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install dependencies run: | python -m pip install -q --upgrade pip python -m pip install -q -r requirements.txt - name: Refresh digest history # Cheap (a few seconds); doesn't touch corpus content. # Without this step, a code-only deploy would ship an # increasingly-stale digest history relative to git. run: | mkdir -p corpus/.digest python -m scrape.changelog \ --history-out corpus/.digest/history.jsonl \ --history-days 120 - name: Verify committed corpus is present run: | test -d corpus || { echo "ERROR: corpus/ missing on this ref"; exit 1; } echo "corpus: $(du -sh corpus | cut -f1), $(find corpus -name '*.md' | wc -l) markdown files" - name: Rebuild indexes from existing corpus run: python -m rag.index --rebuild - name: Log in to registry (LAN endpoint) run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login "${REGISTRY_PUSH}" -u "${{ github.repository_owner }}" --password-stdin - name: Build & push image run: | SHA_TAG=$(echo "$GITHUB_SHA" | cut -c1-12) DATE_TAG=$(date -u +%Y.%m.%d) docker build \ -t "${REGISTRY_PUSH}/${IMAGE}:latest" \ -t "${REGISTRY_PUSH}/${IMAGE}:${SHA_TAG}" \ -t "${REGISTRY_PUSH}/${IMAGE}:${DATE_TAG}" \ . docker push "${REGISTRY_PUSH}/${IMAGE}:latest" docker push "${REGISTRY_PUSH}/${IMAGE}:${SHA_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 env: GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }} run: | python scripts/registry_gc.py \ --owner "${{ github.repository_owner }}" \ --package "${{ github.event.repository.name }}" \ --keep-days 90 \ --keep-latest 5