Compile in CI
zipline compile turns your Python confs into the compiled/ output that the Hub reads. Instead of
running it locally before every commit, you can let CI run it on each push and commit the output
back to the branch. This is what makes editing confs in the Zipline UI work end to end: you edit and
commit a .py file in the browser, and CI produces the matching compiled confs.
One zipline compile builds every environment in the repo (teams.py → compiled/, teams.canary.py → compiled_canary/), so there is nothing to choose per environment. See Multi-Environment Compile & Deploy.
GitHub Actions workflow
Add .github/workflows/zipline_compile.yaml to your conf repo. Adjust CONF_ROOT (the folder
containing teams.py), the paths filters to match it, and the zipline-ai version to match your
Hub.
name: Zipline compile
on:
push:
paths:
- "confs/**"
# Its own output; also keeps the commit below from re-triggering this workflow
- "!confs/compiled/**"
- "!confs/compiled_*/**"
workflow_dispatch:
# A newer push to the same branch supersedes an in-flight compile
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
compile:
name: Zipline compile
runs-on: ubuntu-latest
permissions:
contents: write
env:
CONF_ROOT: confs
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install Zipline CLI
run: pip install "zipline-ai==<your Hub version>"
# --force skips the interactive confirmation for changed confs. Unsafe in-place changes to
# confs that are already online still fail the job.
- name: Compile
working-directory: ${{ env.CONF_ROOT }}
run: zipline compile --force
- name: Commit compiled confs
if: github.ref != format('refs/heads/{0}', github.event.repository.default_branch)
run: |
# Quoted so git matches compiled/ and every compiled_<env>/, and nothing else
git add -A -- "${CONF_ROOT}/compiled*"
if git diff --cached --quiet; then
echo "Compiled confs are up to date."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git commit -m "Update compiled confs"
if ! git push origin HEAD:"${GITHUB_REF_NAME}"; then
# Someone pushed meanwhile; that push starts its own run, which compiles it
git fetch origin "${GITHUB_REF_NAME}"
if [ "$(git rev-parse FETCH_HEAD)" != "${GITHUB_SHA}" ]; then
echo "::notice::${GITHUB_REF_NAME} moved during compile; the newer run will commit its output."
exit 0
fi
exit 1
fi
# The default branch is usually protected, so verify instead of pushing to it
- name: Verify compiled confs are up to date
if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
run: |
git add -A -- "${CONF_ROOT}/compiled*"
if ! git diff --cached --quiet; then
echo "::error::Compiled confs are out of date. Run 'zipline compile' in ${CONF_ROOT} and commit the result."
git diff --cached --stat
exit 1
fiIf your confs live at the repository root, use CONF_ROOT: . and filter on "**" with the same !compiled/** and !compiled_*/** exclusions.
How it behaves
- Feature branches: each push that changes a conf compiles it, and any change to the compiled
output is committed back to the branch as
Update compiled confs. Review it in the pull request alongside the source change. - The default branch: the job only verifies that the committed output is current. Merge through pull requests so the compiled output is already on the branch.
- Compile errors fail the job and nothing is committed. This includes changing a conf that is already running online without bumping its version: compile refuses to overwrite it, so the change has to go out as a new version.
- The output is deterministic. The same confs always produce the same compiled files, and
removed confs disappear from
compiled/, so the commit contains only real changes. - No credentials are needed. Compile reads your confs and writes files; it doesn't contact the
Hub or your warehouse. Uploading still happens through your deploy step
(
zipline hub schedule-allor the Hub UI).
Things to know
- The compile commit doesn't start other workflows. GitHub doesn't run workflows for commits
pushed with the default
GITHUB_TOKEN, so theUpdate compiled confscommit has no checks of its own. If your branch protection requires checks on the latest commit, push with a GitHub App token instead (pass it toactions/checkoutastoken). - Pull requests from forks can't be pushed to by the workflow. Contributors from forks need to
run
zipline compilethemselves. - Environment variables your
teams.pyreads (for exampleos.environ.get(...)for a version string) end up in the compiled output. Keep them unset in this job, or set them to the values you want committed. - Pin the CLI version to the one your Hub runs, and upgrade both together, so the compiled output matches what the Hub expects.
- Seeing the result in the Zipline UI: the editor's Checks tab shows this job's status when the GitHub connection has the Checks: read and Commit statuses: read permissions.