From 630b4a3e5534dbf481e23cf5fd4f15c3260c6018 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Wed, 7 Oct 2026 10:30:03 +0800 Subject: [PATCH 1/3] build: derive package versions from Git --- .dockerignore | 2 ++ .github/workflows/main.yml | 10 +++++++++- .github/workflows/on-release-main.yml | 9 ++++++++- Dockerfile | 1 + README.md | 8 ++++---- compose.yaml | 2 +- docs/development.md | 6 ++++-- docs/get-started.md | 4 ++-- docs/guides/ci.md | 2 +- docs/guides/deploy.md | 4 ++-- docs/guides/local.md | 4 +++- docs/guides/mcp.md | 2 +- docs/guides/server.md | 2 +- docs/reference/cli.md | 2 +- pyproject.toml | 11 +++++++++-- uv.lock | 1 - 16 files changed, 49 insertions(+), 21 deletions(-) diff --git a/.dockerignore b/.dockerignore index 0d91b06..6c84b4f 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,6 +7,8 @@ !src/landing/*.py !src/landing/adapters/ !src/landing/adapters/*.py +!src/skills/ +!src/skills/** !container/ !container/entrypoint !container/litestream.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 707e100..3cf49d8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -54,6 +54,8 @@ jobs: steps: - name: Check out uses: actions/checkout@v7 + with: + fetch-depth: 0 - uses: actions/cache@v6 with: @@ -82,6 +84,8 @@ jobs: steps: - name: Check out uses: actions/checkout@v7 + with: + fetch-depth: 0 - name: Set up the environment uses: ./.github/actions/setup-python-env @@ -101,6 +105,8 @@ jobs: steps: - name: Check out uses: actions/checkout@v7 + with: + fetch-depth: 0 - name: Set up the environment uses: ./.github/actions/setup-python-env @@ -112,9 +118,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + with: + fetch-depth: 0 - uses: ./.github/actions/setup-python-env - name: Build the ONCE-compatible image - run: docker build -t landing:ci . + run: docker build --build-arg SETUPTOOLS_SCM_PRETEND_VERSION="$(uv run landing --version)" -t landing:ci . - name: Check the container and both backup recovery paths run: uv run python tests/container_smoke.py --image landing:ci diff --git a/.github/workflows/on-release-main.yml b/.github/workflows/on-release-main.yml index 970ce17..592b936 100644 --- a/.github/workflows/on-release-main.yml +++ b/.github/workflows/on-release-main.yml @@ -14,12 +14,14 @@ jobs: steps: - name: Check out uses: actions/checkout@v7 + with: + fetch-depth: 0 - name: Set up the environment uses: ./.github/actions/setup-python-env - name: Verify release tag matches the package version - run: test "$(uv version --short)" = "$RELEASE_VERSION" + run: test "$(uv run landing --version)" = "$RELEASE_VERSION" env: RELEASE_VERSION: ${{ github.ref_name }} @@ -40,6 +42,8 @@ jobs: packages: write steps: - uses: actions/checkout@v7 + with: + fetch-depth: 0 - uses: docker/setup-buildx-action@v4 - uses: docker/login-action@v4 with: @@ -54,6 +58,7 @@ jobs: - uses: docker/build-push-action@v7 with: context: . + build-args: SETUPTOOLS_SCM_PRETEND_VERSION=${{ github.ref_name }} push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} @@ -75,6 +80,8 @@ jobs: steps: - name: Check out uses: actions/checkout@v7 + with: + fetch-depth: 0 - name: Set up the environment uses: ./.github/actions/setup-python-env diff --git a/Dockerfile b/Dockerfile index 9aee221..2e17e2a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ COPY --from=uv /uv /uvx /usr/local/bin/ WORKDIR /opt/landing COPY pyproject.toml uv.lock README.md ./ COPY src ./src +ARG SETUPTOOLS_SCM_PRETEND_VERSION RUN uv sync --frozen --no-dev --no-editable --no-cache FROM python:3.12-slim-bookworm diff --git a/README.md b/README.md index bc50122..bbc4d81 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Configure CI -> Open a PR -> Read the feedback -> Decide what to accept Set the `LANDING_MODEL` repository variable and `LANDING_API_KEY` secret, and grant the review job `contents: read` and `pull-requests: write`. After checkout and successful native checks, add this step to your existing workflow: ```yaml -- uses: bubbuild/landing@0.2.0 +- uses: bubbuild/landing@main continue-on-error: true env: GH_TOKEN: ${{ github.token }} @@ -31,7 +31,7 @@ Set the `LANDING_MODEL` repository variable and `LANDING_API_KEY` secret, and gr instruction: Native checks passed for this checkout. Review this PR using repository guidance and publish actionable findings inline. ``` -`continue-on-error` keeps automatic feedback advisory; inspect the Action logs if no review appears. The Action uses your authenticated `gh`, project tools, and skills. It checks who can delegate before starting the agent. See [CI integration](https://getlanding.dev/guides/ci/) for other CI systems and [GitHub integration](https://getlanding.dev/guides/github/) for `/landing` commands, publishing identities, and trust policy. +The example follows `main`; pin a release tag or reviewed commit to keep the runtime fixed. `continue-on-error` keeps automatic feedback advisory; inspect the Action logs if no review appears. The Action uses your authenticated `gh`, project tools, and skills. It checks who can delegate before starting the agent. See [CI integration](https://getlanding.dev/guides/ci/) for other CI systems and [GitHub integration](https://getlanding.dev/guides/github/) for `/landing` commands, publishing identities, and trust policy. To build the same review and delegated-fix experience, ask your agent to read [Landing's workflows](https://github.com/bubbuild/landing/tree/main/.github/workflows) and [development guide](https://getlanding.dev/development/), then adapt the CI setup to your repository's tools and checks. @@ -40,7 +40,7 @@ To build the same review and delegated-fix experience, ask your agent to read [L With Python 3.12 or later, [uv](https://docs.astral.sh/uv/), and a POSIX host: ```bash -uv tool install "landing==0.2.0" +uv tool install landing export LANDING_MODEL="openai:gpt-4.1" export LANDING_API_KEY="your-provider-api-key" landing explain "Explain this failure and the next useful check." --input check.log @@ -52,6 +52,6 @@ Run from your project checkout and use a saved UTF-8 log for `check.log`. The co Reliable results draw on your documentation, work items, infrastructure, tests, benchmarks, and observability. [Working with Landing](https://getlanding.dev/working-with-landing/) explains how to connect that context and retain feedback. Automate the engineering work you can delegate, and use the time saved to stay involved with contributors and users. Community Over Code. -[Make Landing work for you](https://getlanding.dev/make-it-yours/) covers project instructions, skills, and tools. For shared execution, [run the server](https://getlanding.dev/guides/server/) or [deploy the container](https://getlanding.dev/guides/deploy/) from `ghcr.io/bubbuild/landing:0.2.0`. Actions and model history are stored in SQLite; workspace files stay in your workspace, and model requests go to your chosen provider. +[Make Landing work for you](https://getlanding.dev/make-it-yours/) covers project instructions, skills, and tools. For shared execution, [run the server](https://getlanding.dev/guides/server/) or [deploy the container](https://getlanding.dev/guides/deploy/) from `ghcr.io/bubbuild/landing:latest`. Actions and model history are stored in SQLite; workspace files stay in your workspace, and model requests go to your chosen provider. [Contributions](https://github.com/bubbuild/landing/blob/main/CONTRIBUTING.md) are welcome. Licensed under [Apache-2.0](https://github.com/bubbuild/landing/blob/main/LICENSE). Powered by [Bub](https://bub.build/) and [tape.systems](https://tape.systems/). diff --git a/compose.yaml b/compose.yaml index 05f585e..6d27a3c 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,7 +1,7 @@ services: landing: build: . - image: ${LANDING_IMAGE:-ghcr.io/bubbuild/landing:0.2.0} + image: ${LANDING_IMAGE:-ghcr.io/bubbuild/landing:latest} restart: unless-stopped ports: - "127.0.0.1:8080:80" diff --git a/docs/development.md b/docs/development.md index cdb96ba..5e17cc2 100644 --- a/docs/development.md +++ b/docs/development.md @@ -105,7 +105,9 @@ Bundled jobs use a 120-second model request timeout. Main's feedback Action has ## Publish a release -Set the version with `uv version VERSION` and update installation examples and Action references. After validation and merge, publish a GitHub release with the matching unprefixed tag, such as `0.2.0`. The workflow verifies the version, publishes to PyPI and GHCR, and deploys the documentation. The tag also selects the Action; stable images update `latest`. +Versions come from Git tags through `hatch-vcs`; untagged commits receive development versions with a commit hash. CLI and API versions use installed package metadata. Archives without Git or package metadata use `0.0.0`; the standard `SETUPTOOLS_SCM_PRETEND_VERSION` variable supplies a version when building the container. + +After validation and merge, publish a GitHub release with an unprefixed version tag for the intended release. The workflow verifies the version, publishes to PyPI and GHCR, and deploys the documentation. The tag also selects the Action; stable images update `latest`. ## Learn from outcomes @@ -118,7 +120,7 @@ Keep investigation details in artifacts and public feedback useful to the person With Docker or Podman: ```bash -docker build -t landing:local . +docker build --build-arg SETUPTOOLS_SCM_PRETEND_VERSION="$(uv run landing --version)" -t landing:local . uv run python tests/container_smoke.py --image landing:local ``` diff --git a/docs/get-started.md b/docs/get-started.md index 0b50a91..25e1a2f 100644 --- a/docs/get-started.md +++ b/docs/get-started.md @@ -17,7 +17,7 @@ Use your actual repository and provider model. The secret command prompts for th ## Add the workflow -Save the following as `.github/workflows/review.yml`. The example pins Landing to release `0.2.0`; you can pin it to a reviewed commit instead. Your workflow prepares the project and runs native checks, then calls Landing once. The Action checks the event and caller before starting the agent. +Save the following as `.github/workflows/review.yml`. The example follows Landing's `main`; pin a release tag or reviewed commit to keep the runtime fixed. Your workflow prepares the project and runs native checks, then calls Landing once. The Action checks the event and caller before starting the agent. ```yaml name: Review @@ -39,7 +39,7 @@ jobs: - uses: astral-sh/setup-uv@v10.2.0 - name: Run native checks run: uv sync --locked && uv run pytest - - uses: bubbuild/landing@0.2.0 + - uses: bubbuild/landing@main if: github.event.pull_request.head.repo.full_name == github.repository id: landing timeout-minutes: 20 diff --git a/docs/guides/ci.md b/docs/guides/ci.md index 00724f3..ccbd955 100644 --- a/docs/guides/ci.md +++ b/docs/guides/ci.md @@ -42,7 +42,7 @@ For explicit delegations that must be preserved, GitHub.com supports `queue: max ## Use an ordinary CI command -Install Landing with `uv tool install "landing==0.2.0"` and configure the model on the executing host. Run commands from your project checkout or select one with `--workspace`. +Install Landing with `uv tool install landing` and configure the model on the executing host. Run commands from your project checkout or select one with `--workspace`. Preserve the native check's exit status when asking for an explanation: diff --git a/docs/guides/deploy.md b/docs/guides/deploy.md index 9652bf4..ffb119f 100644 --- a/docs/guides/deploy.md +++ b/docs/guides/deploy.md @@ -1,6 +1,6 @@ # Deploy Landing -Use the released image `ghcr.io/bubbuild/landing:0.2.0`. Stable releases also update `latest`; pin a version or digest for deployment. Prepare model settings and a project workspace with the tools its tasks need. +Use `ghcr.io/bubbuild/landing:latest` for the latest stable release. Pin a release tag or digest to keep the deployed image fixed. Prepare model settings and a project workspace with the tools its tasks need. ## Start with Compose @@ -32,7 +32,7 @@ The image follows [ONCE's application contract](https://github.com/basecamp/once Configure the [replica destination](recovery.md#replicate-the-database) and credentials before deployment: ```bash -once deploy ghcr.io/bubbuild/landing:0.2.0 --host landing.example.com --env "LANDING_TOKEN=$LANDING_TOKEN" --env "LANDING_MODEL=$LANDING_MODEL" --env "LANDING_API_KEY=$LANDING_API_KEY" --env "LITESTREAM_REPLICA_URL=$LITESTREAM_REPLICA_URL" --env "AWS_REGION=$AWS_REGION" --env "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" --env "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" +once deploy ghcr.io/bubbuild/landing:latest --host landing.example.com --env "LANDING_TOKEN=$LANDING_TOKEN" --env "LANDING_MODEL=$LANDING_MODEL" --env "LANDING_API_KEY=$LANDING_API_KEY" --env "LITESTREAM_REPLICA_URL=$LITESTREAM_REPLICA_URL" --env "AWS_REGION=$AWS_REGION" --env "AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID" --env "AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY" ``` Enable ONCE's full-volume backups for workspace files. Landing uses paused-container backup behavior. Litestream protects SQLite separately; [Recovery](recovery.md) describes both paths. Verify deployment and remote replication in your actual environment. diff --git a/docs/guides/local.md b/docs/guides/local.md index 8e4cd22..ca5e7e4 100644 --- a/docs/guides/local.md +++ b/docs/guides/local.md @@ -3,11 +3,13 @@ Run a task against your own checkout with Python 3.12 or later, uv, and a POSIX host. Install Landing as an isolated tool, then prepare your project dependencies and checks: ```bash -uv tool install "landing==0.2.0" +uv tool install landing export LANDING_MODEL="openai:gpt-4.1" export LANDING_API_KEY="your-provider-api-key" ``` +This installs the latest release. Update it with `uv tool upgrade landing`. For a development build from `main`, use `uv tool install --force git+https://github.com/bubbuild/landing.git`; its version identifies the source revision. + Run commands from your project checkout. If `landing` is not on your PATH after installation, run `uv tool update-shell` and restart your shell. For another provider or endpoint, see [Configuration](../reference/configuration.md#model). ## Explain a failure diff --git a/docs/guides/mcp.md b/docs/guides/mcp.md index f67cbbc..ae87fce 100644 --- a/docs/guides/mcp.md +++ b/docs/guides/mcp.md @@ -5,7 +5,7 @@ Add trusted server definitions to `.agents/mcp.json` in your workspace. Prepare The repository includes a [Playwright MCP example](https://github.com/bubbuild/landing/blob/main/.agents/mcp.json). Prepare Node.js and Chrome, then adapt its arguments to your environment. Install Landing: ```bash -uv tool install "landing==0.2.0" +uv tool install landing ``` Delegate work through the usual command: diff --git a/docs/guides/server.md b/docs/guides/server.md index 30765b9..1c55e0f 100644 --- a/docs/guides/server.md +++ b/docs/guides/server.md @@ -1,6 +1,6 @@ # Run the server -Use a service for a shared queue or HTTP admission point. Prepare checkouts, dependencies, model settings, and skills on the executing host. Install the CLI with `uv tool install "landing==0.2.0"`. +Use a service for a shared queue or HTTP admission point. Prepare checkouts, dependencies, model settings, and skills on the executing host. Install the CLI with `uv tool install landing`. ## Start with registered workspaces diff --git a/docs/reference/cli.md b/docs/reference/cli.md index f7a5c3d..bc8632f 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -84,7 +84,7 @@ In GitHub Actions, the command reads `GITHUB_EVENT_PATH` and the Action's `INPUT ## GitHub Action -`bubbuild/landing@0.2.0` executes work from GitHub workflow events. [Get started](../get-started.md) shows project preparation and one Action invocation with built-in admission. +The `bubbuild/landing` Action executes work from GitHub workflow events. [Get started](../get-started.md) shows project preparation and one Action invocation with built-in admission. | Input | Contract | | --- | --- | diff --git a/pyproject.toml b/pyproject.toml index 2c17757..22eee94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "landing" -version = "0.2.0" +dynamic = ["version"] description = "Explain CI failures, delegate fixes, and review evidence with your own tools." authors = [{ name = "Chojan Shang", email = "psiace@apache.org" }] readme = "README.md" @@ -54,15 +54,22 @@ dev = [ ] [build-system] -requires = ["hatchling"] +requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" +[tool.hatch.version] +source = "vcs" +fallback-version = "0.0.0" + [tool.hatch.build] exclude = ["/.lody", "/.ci-state", "*.sqlite", "*.sqlite-*", "*.sqlite3", "*.sqlite3-*"] [tool.hatch.build.targets.wheel] packages = ["src/landing", "src/skills"] +[tool.uv] +cache-keys = [{ file = "pyproject.toml" }, { git = { commit = true, tags = true } }, { env = "SETUPTOOLS_SCM_PRETEND_VERSION" }] + [tool.ty.environment] python = "./.venv" python-version = "3.12" diff --git a/uv.lock b/uv.lock index a7b5d60..07f8929 100644 --- a/uv.lock +++ b/uv.lock @@ -1159,7 +1159,6 @@ wheels = [ [[package]] name = "landing" -version = "0.2.0" source = { editable = "." } dependencies = [ { name = "bub" }, From 2b7a6f8a19003ff57ca245973aa1afbffd3eb016 Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Wed, 7 Oct 2026 12:05:06 +0800 Subject: [PATCH 2/3] fix: preserve versions in GitHub source archives --- .git_archival.txt | 3 +++ .gitattributes | 1 + docs/development.md | 2 +- pyproject.toml | 4 ++-- 4 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 .git_archival.txt create mode 100644 .gitattributes diff --git a/.git_archival.txt b/.git_archival.txt new file mode 100644 index 0000000..7c51009 --- /dev/null +++ b/.git_archival.txt @@ -0,0 +1,3 @@ +node: $Format:%H$ +node-date: $Format:%cI$ +describe-name: $Format:%(describe:tags=true,match=*[0-9]*)$ diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..a94cb2f --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.git_archival.txt export-subst diff --git a/docs/development.md b/docs/development.md index 5e17cc2..e774d39 100644 --- a/docs/development.md +++ b/docs/development.md @@ -105,7 +105,7 @@ Bundled jobs use a 120-second model request timeout. Main's feedback Action has ## Publish a release -Versions come from Git tags through `hatch-vcs`; untagged commits receive development versions with a commit hash. CLI and API versions use installed package metadata. Archives without Git or package metadata use `0.0.0`; the standard `SETUPTOOLS_SCM_PRETEND_VERSION` variable supplies a version when building the container. +Versions come from Git tags through `hatch-vcs`; untagged commits receive development versions with a commit hash. GitHub source archives carry version metadata for Action installation. CLI and API versions use installed package metadata. Source copies without Git, archive, or package metadata use `0.0.0`; the standard `SETUPTOOLS_SCM_PRETEND_VERSION` variable supplies a version when building the container. After validation and merge, publish a GitHub release with an unprefixed version tag for the intended release. The workflow verifies the version, publishes to PyPI and GHCR, and deploys the documentation. The tag also selects the Action; stable images update `latest`. diff --git a/pyproject.toml b/pyproject.toml index 22eee94..11dd35f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -62,13 +62,13 @@ source = "vcs" fallback-version = "0.0.0" [tool.hatch.build] -exclude = ["/.lody", "/.ci-state", "*.sqlite", "*.sqlite-*", "*.sqlite3", "*.sqlite3-*"] +exclude = ["/.lody", "/.ci-state", "/.git_archival.txt", "*.sqlite", "*.sqlite-*", "*.sqlite3", "*.sqlite3-*"] [tool.hatch.build.targets.wheel] packages = ["src/landing", "src/skills"] [tool.uv] -cache-keys = [{ file = "pyproject.toml" }, { git = { commit = true, tags = true } }, { env = "SETUPTOOLS_SCM_PRETEND_VERSION" }] +cache-keys = [{ file = "pyproject.toml" }, { file = ".git_archival.txt" }, { git = { commit = true, tags = true } }, { env = "SETUPTOOLS_SCM_PRETEND_VERSION" }] [tool.ty.environment] python = "./.venv" From b2861c980b6b7fc9ce72fa43d8787cc477571efb Mon Sep 17 00:00:00 2001 From: Chojan Shang Date: Wed, 7 Oct 2026 12:20:18 +0800 Subject: [PATCH 3/3] fix: forward package versions to Compose builds --- compose.yaml | 5 ++++- docs/development.md | 2 +- docs/guides/deploy.md | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/compose.yaml b/compose.yaml index 6d27a3c..621d03c 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,6 +1,9 @@ services: landing: - build: . + build: + context: . + args: + SETUPTOOLS_SCM_PRETEND_VERSION: ${SETUPTOOLS_SCM_PRETEND_VERSION:-} image: ${LANDING_IMAGE:-ghcr.io/bubbuild/landing:latest} restart: unless-stopped ports: diff --git a/docs/development.md b/docs/development.md index e774d39..cf21d95 100644 --- a/docs/development.md +++ b/docs/development.md @@ -120,7 +120,7 @@ Keep investigation details in artifacts and public feedback useful to the person With Docker or Podman: ```bash -docker build --build-arg SETUPTOOLS_SCM_PRETEND_VERSION="$(uv run landing --version)" -t landing:local . +docker build --build-arg SETUPTOOLS_SCM_PRETEND_VERSION="$(uv run --reinstall-package landing landing --version)" -t landing:local . uv run python tests/container_smoke.py --image landing:local ``` diff --git a/docs/guides/deploy.md b/docs/guides/deploy.md index ffb119f..f05f6b2 100644 --- a/docs/guides/deploy.md +++ b/docs/guides/deploy.md @@ -23,7 +23,7 @@ curl -i http://127.0.0.1:8080/v1/actions -H "Authorization: Bearer $LANDING_TOKE The response contains a task receipt; [Run the server](server.md) explains result inspection and cancellation. -Use `compose.yaml` from the Landing repository. `LANDING_IMAGE` selects another image or digest. For a local build, set `LANDING_IMAGE=landing:local` and run `docker compose up --build -d`. Compose forwards only the listed variables; use an override for additional settings or mounts. See [Configuration](../reference/configuration.md#container-replication). `/up` is also the container healthcheck. Each database has one worker. +Use `compose.yaml` from the Landing repository. `LANDING_IMAGE` selects another image or digest. For a local build, run `LANDING_IMAGE=landing:local SETUPTOOLS_SCM_PRETEND_VERSION="$(uv run --reinstall-package landing landing --version)" docker compose up --build -d` from the repository checkout. Compose forwards only the listed variables; use an override for additional settings or mounts. See [Configuration](../reference/configuration.md#container-replication). `/up` is also the container healthcheck. Each database has one worker. ## Deploy with ONCE