Skip to content

chore(ci): trunk-based deploys - #7

Merged
JonnyTran merged 16 commits into
mainfrom
chore/trunk-based-deploys
Aug 6, 2026
Merged

chore(ci): trunk-based deploys#7
JonnyTran merged 16 commits into
mainfrom
chore/trunk-based-deploys

Conversation

@JonnyTran

@JonnyTran JonnyTran commented Aug 5, 2026

Copy link
Copy Markdown
Member

Part 1 of the gitflow → trunk-based migration. Merging this makes main the trunk for this repo.

This repo builds nothing on its own schedule — it is dispatch-driven by the extralit monorepo. 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-env in build-hf-space.yml no longer routes on branch names. is_release is now the only production signal:

Dispatch payload Environment Platforms Deploys to
is_release: true production amd64 + arm64 extralit/public-demo
branch: main (or develop) staging amd64 extralit-dev/develop
branch: <n>/merge, anything else staging amd64 ephemeral extralit-dev/pr-<n>

A payload without is_release: true cannot select production, whatever branch it claims to come from. This also fixes the releases/** hole, where a push dispatched branch=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-space jobs are unchanged — they already read DOCKER_REPO, EXTRALIT_SERVER_IMAGE, and HF_SPACE_ID from per-environment variables.

Also: integration-test.yml runs on [main, release]; deploy_pr_space.py docstrings say "staging"; CLAUDE.md gains a "Branching & deploy" section (it documented none).

Two behaviour changes to be aware of

  1. workflow_dispatch can no longer reach production. A manual run carries no client_payload, so it always resolves to staging. Previously a manual run on main selected the main environment and could push to the production registry. To redeploy production, re-run the original dispatch-triggered run from the Actions UI — that replays its client_payload.
  2. develop is kept as a staging alias, 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.

⚠️ Required before the monorepo flip

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.

Old env New env DOCKER_REPO EXTRALIT_SERVER_IMAGE HF_SPACE_ID
main production extralit/extralit-hf-space extralit/extralit-server extralit/public-demo
develop staging extralitdev/extralit-hf-space extralitdev/extralit-server extralit-dev/develop

The 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 main and delete develop.

Not a mistake: SOURCE_SPACE: extralit-dev/develop

That is a Hugging Face Space, not a git branch, and the custom OAuth app is pinned to its extralit-dev-develop.hf.space callback. Renaming the Space breaks login. It's the one place the word "develop" legitimately survives, and there's now a comment saying so.

Verification

  • actionlint passes on all workflows.
  • The resolve-env run: body was extracted from the YAML and executed against 9 dispatch payloads plus the unsupported-event guard — 10/10 as expected. Notably is_release="" with branch=release resolves to staging, not production.
  • Merges cleanly into main: the one main-side commit (e56d020, a Dockerfile ARG default) touches a non-overlapping hunk; git merge-tree reports 0 conflicts.

Prefer a merge commit over squash so develop's 13 commits keep their identity.

Summary by CodeRabbit

  • New Features

    • Added automated preview environments for pull requests, including creation, reuse, configuration, and deployment status reporting.
    • Added support for dispatch-driven production, staging, and preview deployments.
    • Updated container networking to use port 6900 for HTTP traffic.
  • Improvements

    • Deployment workflows now apply environment-specific settings and release tagging more consistently.
    • Integration tests now run for main and release branches.
    • Updated project build and dependency configuration.

JonnyTran and others added 15 commits September 22, 2025 19:59
- 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.
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 266a4fd0-6879-4c25-9f7e-5d033c8206f1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between e56d020 and 35086a6.

📒 Files selected for processing (6)
  • .github/workflows/build-hf-space.yml
  • .github/workflows/integration-test.yml
  • CLAUDE.md
  • Dockerfile
  • pyproject.toml
  • scripts/deploy_pr_space.py

Comment thread .github/workflows/build-hf-space.yml
Comment thread .github/workflows/build-hf-space.yml
Comment thread .github/workflows/build-hf-space.yml Outdated
Comment thread .github/workflows/build-hf-space.yml Outdated
Comment thread .github/workflows/integration-test.yml Outdated
Comment thread scripts/deploy_pr_space.py
Comment thread scripts/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.
@JonnyTran
JonnyTran merged commit aa6077d into main Aug 6, 2026
2 checks passed
@JonnyTran
JonnyTran deleted the chore/trunk-based-deploys branch August 6, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant