chore(ci): trunk-based deploys - #7
Conversation
- Introduced a new step in the build-hf-space workflow to test the EXTRALIT_SERVER_IMAGE before building and pushing the Docker image. - The test runs a command to verify the server starts correctly, enhancing the CI process.
- Introduced a new step in the build-hf-space workflow to test before building and pushing the Docker image. - The test runs a command to verify the server starts correctly, enhancing the CI process.
…ependency management - Removed local development instructions from CLAUDE.md to streamline documentation. - Updated pyproject.toml to replace PDM with Hatchling as the build backend and adjusted dependency specifications accordingly. - Organized optional dependencies under a new section for better clarity.
Replace hardcoded conditionals with `main` and `develop` GitHub Environments that carry per-env Docker credentials, repo names, and HF Space IDs. Split workflow into resolve-env + build jobs so the environment is selected dynamically from dispatch payload or branch name. Add HF Space restart step after Docker push. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Dockerfile exposed port 80 but uvicorn listens on 6900 (set in the base extralit-server image). This mismatch could cause issues with port auto-detection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow arbitrary branches (not just main/develop) to build and deploy to HF Space branch revisions under the develop environment. Feature branches get a sanitized branch name on the HF Space with a Dockerfile pointing to the branch-specific Docker image tag. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
HF Spaces only deploy from the main branch, so branch-based deployments don't work. Instead, duplicate the source Space to a new PR-specific Space (e.g. extralit-dev/pr-201) and upload a Dockerfile pointing to the PR Docker image. Uses repo-level HF_TOKEN secret for PR deploys (no environment needed). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DOCKER_REPO was empty because deploy-pr-space has no environment. Hardcode the dev Docker repo. Also pass hardware="cpu-basic" which is required by the HF duplicate_space API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The source Space's Dockerfile copies .oauth.yaml into the container for HF OAuth config. The PR Space Dockerfile was missing this, which likely causes the extralit server to crash on startup, triggering honcho to SIGKILL all processes including Elasticsearch. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed the destination path for copying .oauth.yaml in the Dockerfile from /home/argilla/ to /home/extralit/. This ensures the correct configuration is used for the extralit server during deployment.
- Split deploy into deploy-space (restart main/develop) and deploy-pr-space (PR previews) - Use HF's built-in OAuth (hf_oauth: true in README) instead of .oauth.yaml file - Update source space from extralit-dev/public-demo to extralit-dev/develop - Consolidate PR space logic into single script with create-if-needed + always-update Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
deploy-pr-space duplicates extralit-dev/develop, but duplicate_space does not copy a Space's secrets/variables, so a fresh pr-N Space had no DB/S3/auth config. Now forward the develop GitHub environment's EXTRALIT_* values onto the Space (env secrets -> Space secrets, env variables -> Space variables), strictly filtered to the EXTRALIT_ prefix so HF_TOKEN/DOCKER_*/GITHUB_TOKEN are never pushed. No-op when no EXTRALIT_* keys are set. Extract the inline Python into scripts/deploy_pr_space.py and check out the repo in the job so it can be invoked.
Prepares this repo for the trunk-based migration without yet changing any routing logic: - integration-test.yml: run on `main` and `release`, not `develop` - deploy_pr_space.py + deploy-pr-space comment: the PR-preview config is sourced from what will be the `staging` environment - CLAUDE.md: document branching & the dispatch→environment mapping, which was previously undocumented Also pins down why SOURCE_SPACE stays `extralit-dev/develop`: it is a Hugging Face Space, not a branch, and its OAuth callback is pinned to that name. resolve-env itself is rewritten in the next commit.
Replaces the branch-name `case` with an `is_release`-first conditional, so branch names stop being load-bearing for deploy targeting: - is_release=true -> production, amd64+arm64, :latest - main (or develop alias) -> staging, amd64, :latest - anything else -> staging, amd64, ephemeral pr-<n> Space Environments are renamed main/develop -> production/staging so the names survive the trunk rename; the jobs read DOCKER_REPO / EXTRALIT_SERVER_IMAGE / HF_SPACE_ID from environment vars and needed no changes. Two behaviour changes worth calling out: - workflow_dispatch can no longer reach production. It carries no client_payload, so it always resolves to staging. Re-running the original dispatch-triggered run replays its payload if a production redeploy is needed. - `develop` is kept as a staging alias so dispatches still in flight from the pre-trunk monorepo don't spin up a preview Space. Remove it once the trunk flip is verified. Slug truncation moves from `| head -c 50` to parameter expansion so the step's exit status isn't coupled to a pipeline that only cuts a string. Verified by executing the extracted `run:` body against 9 dispatch payloads plus the unsupported-event guard; actionlint passes on all workflows.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/build-hf-space.yml:
- Line 1: Update the workflow’s top-level permissions to grant only contents:
read, and set persist-credentials: false on both actions/checkout steps. Apply
the checkout change to the steps near the workflow start and the additional
checkout block identified in the diff.
- Around line 70-74: The preview slug generation around slug and PR_SPACE_SLUG
must include a stable short hash derived from the original BRANCH value, so
branches that normalize identically remain distinct. Compute the hash before
truncating and append it to the sanitized slug while keeping the final
PR_SPACE_SLUG within the 50-character limit.
- Around line 169-170: Update the workflow environment configuration around
SOURCE_SPACE and DOCKER_REPO to read DOCKER_REPO from the staging GitHub
Environment via vars.DOCKER_REPO instead of hardcoding it. Also replace any
hardcoded EXTRALIT_SERVER_IMAGE and HF_SPACE_ID values in this workflow with
their corresponding GitHub Environment variables.
- Around line 151-154: Update the curl invocation in the Space restart step to
include --fail while retaining the existing -sS options, so HTTP 4xx and 5xx
responses cause the workflow job to fail.
In @.github/workflows/integration-test.yml:
- Line 5: Update the workflow branch trigger to include only main, removing
release from the branches list while preserving the existing main trigger.
In `@scripts/deploy_pr_space.py`:
- Around line 44-50: Define a single explicit preview runtime configuration
allowlist and reuse it in both sites: in scripts/deploy_pr_space.py, update
_filter_extralit to retain only the allowlisted EXTRALIT, S3, and OAuth
configuration keys instead of filtering solely by the EXTRALIT_ prefix; in
.github/workflows/build-hf-space.yml, replace the all-secrets toJSON(secrets)
injection with only entries from that same allowlist.
- Around line 61-66: Update the exception handling around api.space_info in the
deployment flow to catch RepositoryNotFoundError only when
exc.response.status_code equals 404, then create the Space as currently
implemented; re-raise authentication, authorization, rate-limit, transport, and
other errors instead of treating them as missing resources.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: f743cf41-7c4d-4ca3-8cf0-231513b6d206
📒 Files selected for processing (6)
.github/workflows/build-hf-space.yml.github/workflows/integration-test.ymlCLAUDE.mdDockerfilepyproject.tomlscripts/deploy_pr_space.py
Addresses the CodeRabbit review on PR #7. Five of seven threads were valid. The workflow writes nothing to this repository — images go to Docker Hub and Spaces are driven by HF_TOKEN — so the token drops to `contents: read` and both checkouts stop persisting it into .git/config, where the docker build context and the deploy script would otherwise inherit it. `curl` without `--fail` exits 0 on 4xx/5xx, so a rejected Space restart reported a successful production deploy. Now `--fail-with-body`, which fails the job while keeping HF's error JSON visible instead of swallowing it. deploy-pr-space hardcoded DOCKER_REPO while the build job pushed to `vars.DOCKER_REPO`; an environment change could point a preview Space at an image that was never built. It now reads the same source. SOURCE_SPACE stays hardcoded — that one is a Hugging Face resource pinned by its OAuth callback. `except Exception` around `space_info` treated an expired HF_TOKEN, a rate limit, or a connection failure as "Space does not exist" and fell through to duplicate_space. RepositoryNotFoundError covers 401 as well as 404 (the Hub returns 401 rather than leak a private repo's existence), so only a genuine 404 creates the Space and everything else propagates. integration-test.yml still triggered on a `release` branch. That branch is the monorepo's; this repo is dispatch-driven and its trunk is `main` alone. Two threads were refuted rather than applied, and CLAUDE.md is corrected so the premise behind one of them stops being re-derived: the "Configuration" section documented unprefixed `S3_ENDPOINT` and a GitHub-supplied `OAUTH2_HUGGINGFACE_*`, neither of which is real. The server reads `EXTRALIT_S3_*` via `env_prefix`, and HF injects OAuth into `hf_oauth: true` Spaces for start.sh to re-export. The deploy step receives the full secret scope, so its one dependency is pinned to huggingface_hub==1.26.0 rather than resolving latest at run time.
Part 1 of the gitflow → trunk-based migration. Merging this makes
mainthe trunk for this repo.This repo builds nothing on its own schedule — it is dispatch-driven by the
extralitmonorepo. So the dispatch contract has to accept the new payload before the monorepo starts sending it, which is why this lands first.What changes
resolve-envinbuild-hf-space.ymlno longer routes on branch names.is_releaseis now the only production signal:is_release: trueproductionextralit/public-demobranch: main(ordevelop)stagingextralit-dev/developbranch: <n>/merge, anything elsestagingextralit-dev/pr-<n>A payload without
is_release: truecannot selectproduction, whatever branch it claims to come from. This also fixes thereleases/**hole, where a push dispatchedbranch=releases/v0.6.1, fell through the old*)case, and built a PR-preview Space instead of deploying anything.The
build/deploy-space/deploy-pr-spacejobs are unchanged — they already readDOCKER_REPO,EXTRALIT_SERVER_IMAGE, andHF_SPACE_IDfrom per-environment variables.Also:
integration-test.ymlruns on[main, release];deploy_pr_space.pydocstrings say "staging";CLAUDE.mdgains a "Branching & deploy" section (it documented none).Two behaviour changes to be aware of
workflow_dispatchcan no longer reach production. A manual run carries noclient_payload, so it always resolves tostaging. Previously a manual run onmainselected themainenvironment and could push to the production registry. To redeploy production, re-run the original dispatch-triggered run from the Actions UI — that replays itsclient_payload.developis kept as astagingalias, so dispatches still in flight from the pre-trunk monorepo land on staging rather than spinning up a stray preview Space. Remove it once the trunk flip is verified.The GitHub Environments must be renamed — this PR references
production/staging, which do not exist yet. Until they do, deploy jobs will fail to resolve their variables.DOCKER_REPOEXTRALIT_SERVER_IMAGEHF_SPACE_IDmainproductionextralit/extralit-hf-spaceextralit/extralit-serverextralit/public-demodevelopstagingextralitdev/extralit-hf-spaceextralitdev/extralit-serverextralit-dev/developThe targets are already correct; only the names encode gitflow. Secret values can't be read back via the API, so the 6 secrets (
HF_TOKEN,DOCKER_USERNAME,DOCKER_PASSWORD× 2 envs) must be re-entered by hand. This is the only irreducibly manual step in the whole migration.Then:
gh repo edit Extralit/extralit-hf-space --default-branch mainand deletedevelop.Not a mistake:
SOURCE_SPACE: extralit-dev/developThat is a Hugging Face Space, not a git branch, and the custom OAuth app is pinned to its
extralit-dev-develop.hf.spacecallback. Renaming the Space breaks login. It's the one place the word "develop" legitimately survives, and there's now a comment saying so.Verification
actionlintpasses on all workflows.resolve-envrun:body was extracted from the YAML and executed against 9 dispatch payloads plus the unsupported-event guard — 10/10 as expected. Notablyis_release=""withbranch=releaseresolves to staging, not production.main: the one main-side commit (e56d020, aDockerfileARGdefault) touches a non-overlapping hunk;git merge-treereports 0 conflicts.Prefer a merge commit over squash so develop's 13 commits keep their identity.
Summary by CodeRabbit
New Features
Improvements
mainandreleasebranches.