mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-08-01 19:06:01 +00:00
* ci(lark): publish lark-cli-init/broker images (#4532) Add .github/workflows/lark-cli-images.yaml to build and push the two optional Lark sandbox runtime images (Pattern A init container and Pattern B broker sidecar) to GHCR. These track the upstream larksuite/cli version, not the DeerFlow v* release, so the workflow is decoupled from container.yaml / the verify-versions gate: - Trigger via workflow_dispatch (lark_cli_version input) or a lark-cli-v* tag (version read from after the prefix). - Multi-arch linux/amd64,linux/arm64 (the images stage a real arch-dispatched lark-cli binary), via QEMU + Buildx. - Per-component build context: lark-cli-init builds from its own dir (relative COPY), lark-cli-broker from the repo root (it copies the shared build-runtime.sh + the harness lark_broker.py). - Tagged by lark-cli version; no latest; gated on the upstream repo. Docs: document the independent publishing in RELEASING.md and both image READMEs, replacing the "publishing is a fast-follow" notes. Closes #4532 * fix(ci): scope broker build context past root .dockerignore The repo-root .dockerignore excludes the whole `docker/` tree, but the lark-cli-broker image builds from a repo-root context and must COPY `docker/lark-cli-init/build-runtime.sh` and `docker/lark-cli-broker/entrypoint.sh` (plus the harness lark_broker.py). Under root .dockerignore those COPYs fail (excluded from context). Add docker/lark-cli-broker/Dockerfile.dockerignore: BuildKit uses this per-Dockerfile ignore-file instead of the root one for `-f docker/lark-cli-broker/Dockerfile` builds, keeping `docker/` and `backend/` in context while still dropping .git/venv/frontend/docs noise. lark-cli-init is unaffected (it builds from its own dir context). * fix(ci): harden lark-cli version input against shell injection Address PR #4558 review: pass the workflow_dispatch input through an env var instead of interpolating ${{ inputs.lark_cli_version }} directly into the run: script, so a dispatched value can't be expression-injected into the runner shell if the repo gate ever widens. Also fix the multi-arch comment verb (stage -> ships).
187 lines
7.5 KiB
Markdown
187 lines
7.5 KiB
Markdown
# Releasing DeerFlow
|
|
|
|
DeerFlow releases are **tag-driven**: pushing a `v*` git tag triggers the
|
|
publishing workflows. There is no separate release script that bumps versions —
|
|
the maintainer bumps the version sources, updates the changelog, commits, and
|
|
tags. The helper scripts below keep the version sources in lockstep, and CI
|
|
gates the release on them agreeing with the tag.
|
|
|
|
## Version sources
|
|
|
|
A release version must appear, identically, in four places:
|
|
|
|
| File | Field |
|
|
| -------------------------------------- | -------------------- |
|
|
| `backend/pyproject.toml` | `version = "X.Y.Z"` |
|
|
| `frontend/package.json` | `"version": "X.Y.Z"` |
|
|
| `deploy/helm/deer-flow/Chart.yaml` | `version: X.Y.Z` |
|
|
| `deploy/helm/deer-flow/Chart.yaml` | `appVersion: "X.Y.Z"`|
|
|
|
|
Plus the git tag `vX.Y.Z` itself, which is the canonical release identifier.
|
|
|
|
Container images are tagged from the git tag (not from these files), and the
|
|
Helm chart version is validated against the tag — so if any source lags the
|
|
tag, the release is blocked (see [Version gate](#version-gate)).
|
|
|
|
The frontend's in-app About page (Settings ▸ About) is a *derived* consumer, not
|
|
a fifth source: it reads `frontend/package.json`'s version at build time, so it
|
|
tracks the table above automatically with no bump needed. Nightly builds override
|
|
it with the chart's nightly string (`<base>-nightly.<YYYYMMDD>-<short_sha>`) via
|
|
the `APP_VERSION` build-arg in `nightly.yaml`, so a nightly image's About page
|
|
distinguishes it from a release.
|
|
|
|
## Helper scripts
|
|
|
|
- `scripts/bump_version.sh <version>` — set all four fields at once, then
|
|
self-verify. Tolerates a leading `v` (e.g. `v2.1.0`).
|
|
```bash
|
|
scripts/bump_version.sh 2.1.0
|
|
```
|
|
- `scripts/verify_versions.sh [version]` — check that all sources agree. With
|
|
no argument it requires mutual equality; with an argument it requires every
|
|
source to equal it. Exits non-zero on mismatch. Run it locally before tagging
|
|
to catch drift early:
|
|
```bash
|
|
scripts/verify_versions.sh 2.1.0
|
|
```
|
|
|
|
## Release procedure
|
|
|
|
1. **Bump the version** across all sources:
|
|
```bash
|
|
scripts/bump_version.sh 2.1.0
|
|
```
|
|
2. **Update `CHANGELOG.md`**: rename the `## [Unreleased]` section to
|
|
`## [2.1.0] — YYYY-MM-DD` (note the em dash `—`), and add a link reference
|
|
at the bottom of the file:
|
|
```
|
|
[2.1.0]: https://github.com/bytedance/deer-flow/releases/tag/v2.1.0
|
|
```
|
|
Start a fresh `## [Unreleased]` section above it for the next cycle.
|
|
3. **Commit** the version + changelog changes:
|
|
```bash
|
|
git add -A
|
|
git commit -m "release: v2.1.0"
|
|
```
|
|
4. **Tag and push**:
|
|
```bash
|
|
git tag v2.1.0
|
|
git push origin v2.1.0
|
|
```
|
|
Pushing the tag triggers the publishing workflows (below).
|
|
|
|
## What CI publishes on a `v*` tag
|
|
|
|
- `.github/workflows/container.yaml` — builds and pushes `backend`,
|
|
`frontend`, and `provisioner` images to `ghcr.io`, tagged with the release
|
|
version (and `latest` on the default branch).
|
|
- `.github/workflows/chart.yaml` — packages the Helm chart and pushes it as an
|
|
OCI artifact to `ghcr.io`. Users install with:
|
|
```bash
|
|
helm install deer-flow oci://ghcr.io/<owner>/charts/deer-flow --version 2.1.0
|
|
```
|
|
|
|
## Nightly builds
|
|
|
|
`.github/workflows/nightly.yaml` runs on a schedule (and `workflow_dispatch`)
|
|
to publish the same three images plus the chart from unreleased `main`. It is
|
|
**not** gated by the version check (there is no `v*` tag) and it does **not**
|
|
touch the `latest` tag, which stays pinned to the last `v*` release. Every job
|
|
is gated on `github.repository == 'bytedance/deer-flow'`, so it only runs on
|
|
the upstream repo - a scheduled run or manual dispatch on a fork skips all jobs.
|
|
|
|
Artifacts (under the running repo's owner, where `<date>` is `YYYYMMDD`):
|
|
|
|
- Images: `ghcr.io/<owner>/deer-flow-{backend,frontend,provisioner}:nightly`
|
|
(rolling, overwritten each run) and `:nightly-<date>` (pinned to a day, but
|
|
mutable within it - a same-day re-dispatch overwrites it). For a truly
|
|
immutable pin, use `:sha-<short>`.
|
|
- Chart: `oci://ghcr.io/<owner>/charts/deer-flow`, version `<base>-nightly.<date>-<sha>`
|
|
(e.g. `2.1.0-nightly.20260710-77a3652`). The short SHA makes each dispatch's
|
|
chart version unique, so a same-day re-dispatch re-publishes cleanly (OCI
|
|
chart versions are immutable and otherwise can't be overwritten). The
|
|
packaged chart defaults `image.registry=ghcr.io/<owner>` and
|
|
`image.tag=nightly`, so installing it pulls the matching nightly images with
|
|
no values overrides:
|
|
```bash
|
|
helm install deer-flow oci://ghcr.io/<owner>/charts/deer-flow \
|
|
--version 2.1.0-nightly.20260710-77a3652
|
|
```
|
|
|
|
The chart version is patched in-workflow only - `Chart.yaml` and `values.yaml`
|
|
in the repo are never modified.
|
|
|
|
## lark-cli sandbox images
|
|
|
|
The two optional Lark sandbox runtime images — `lark-cli-init` (Pattern A) and
|
|
`lark-cli-broker` (Pattern B) — are **not** part of the `v*` release. They track
|
|
the upstream `larksuite/cli` version, so they publish independently via
|
|
`.github/workflows/lark-cli-images.yaml`:
|
|
|
|
- Trigger with `workflow_dispatch` (a `lark_cli_version` input, e.g. `v1.0.65`)
|
|
or by pushing a `lark-cli-v*` tag (the version is read from after the prefix).
|
|
- Builds multi-arch (`linux/amd64,linux/arm64`) and pushes
|
|
`ghcr.io/<owner>/deer-flow-{lark-cli-init,lark-cli-broker}:<lark-cli-version>`.
|
|
- Gated on `github.repository == 'bytedance/deer-flow'`; not tied to the
|
|
`verify-versions` gate (its version is the lark-cli release, not the DeerFlow
|
|
release), and it never touches `latest`.
|
|
|
|
Both features stay opt-in: the provisioner ignores them until
|
|
`LARK_CLI_INIT_IMAGE` / `LARK_CLI_BROKER_IMAGE` point at a published tag.
|
|
|
|
## Version gate
|
|
|
|
Both publishing workflows call `.github/workflows/verify-versions.yml` as their
|
|
first job. It runs `scripts/verify_versions.sh` against the tag (minus the
|
|
`v`). If any of the four version sources doesn't match the tag, the verify job
|
|
fails and **all** publish jobs are skipped — no images, no chart.
|
|
|
|
When it fails, the job annotation names the offending file and suggests the
|
|
fix:
|
|
|
|
```
|
|
::error::frontend/package.json is '2.0.0' but expected '2.1.0'.
|
|
Tip: run scripts/bump_version.sh 2.1.0 to align all sources.
|
|
```
|
|
|
|
## Pre-releases (RCs)
|
|
|
|
Pre-release tags like `v2.1.0-rc1` are valid `v*` tags and trigger the same
|
|
workflows. The version sources must equal the full pre-release string
|
|
(`2.1.0-rc1`) — the gate compares exact strings. Use the same procedure with
|
|
the rc version:
|
|
|
|
```bash
|
|
scripts/bump_version.sh 2.1.0-rc1
|
|
# update CHANGELOG, commit, tag v2.1.0-rc1, push
|
|
```
|
|
|
|
## Recovering from a failed gate
|
|
|
|
If the gate failed because a source was forgotten:
|
|
|
|
1. Run `scripts/bump_version.sh <version>` to align the sources.
|
|
2. Amend or add a follow-up commit.
|
|
3. Delete and re-create the tag, then push it:
|
|
```bash
|
|
git tag -d v2.1.0
|
|
git tag v2.1.0
|
|
git push origin :refs/tags/v2.1.0
|
|
git push origin v2.1.0
|
|
```
|
|
|
|
Re-pushing the tag re-triggers the workflows. Because the gate blocks **all**
|
|
artifacts when it fails, nothing was published under the bad tag, so re-tagging
|
|
is safe — no images or chart were pushed to overwrite.
|
|
|
|
## Post-release
|
|
|
|
Optionally draft a **GitHub Release** from the tag, pasting the corresponding
|
|
`CHANGELOG.md` section as the release notes. The changelog link references
|
|
point at these release URLs.
|
|
|
|
For the 2.1.0 chart release (the first chart release), pre-`charts/` nightly
|
|
builds remain at the legacy bare `ghcr.io/<owner>/deer-flow` package. That
|
|
package receives no new versions after 2.1.0; delete it or revoke its
|
|
visibility once nothing still pulls from it.
|