Skip to content

Generate Cosmos Boost sidecars into the deploy bundle, not the project, and retire astro dbt cleanup - #2311

Merged
schnie merged 5 commits into
v2from
cosmos-boost-in-bundle
Oct 14, 2026
Merged

schnie merged 5 commits into
v2from
cosmos-boost-in-bundle

Conversation

@schnie

@schnie schnie commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

Why

With cosmos_boost.pre_deploy on, every bundle deploy wrote .astro/dbt_metadata.json (and .astro/manifest.slim.json beside each dbt manifest) into the user's dbt project. That left generated files in the repo to commit or ignore. Turning the setting off left them in place, and the next deploy shipped them stale, which is why astro dbt cleanup existed.

The sidecars now go into the deploy bundle only. Nothing is written into the project, so there is no repo churn and nothing to clean up.

What changes

  • Enabled: the pre-deploy step runs in memory (precompute.Run returns its artifacts instead of writing them), and fileutil.TarGz adds them to the bundle through a TarOverlay. They land at the same relative paths, with the same bytes, that were written into the tree before.
    • Nothing is copied or staged.
    • Whatever sits at an artifact's path (an old sidecar, a link, a directory) is left out, and the fresh sidecar takes its place.
    • A unit fails only when its .astro itself is not a directory.
    • Stamping is still best-effort: a failed unit gives a warning, and the deploy goes on without its sidecar.
  • Unrecognized producer, enabled: the deploy is refused with a manual-removal message when another producer's regular file sits where this deploy adds a fresh sidecar, because the plugin reads that path. The check runs on the artifacts' own paths after the step, and before it says "Cosmos Boost pre-deploy step complete". A foreign file anywhere else ships, for example:
    • beside a manifest.json that is not dbt's;
    • under dbt_packages/ or logs/;
    • a slim manifest with the slim optimization off.
  • Always (enabled or not), in the bundle: a regular .astro/dbt_metadata.json / .astro/manifest.slim.json whose own producer marker names this tool is left out. It is judged by a Skip predicate inside the tarball's own walk, so:
    • the files left out are exactly ones the tarball would have carried;
    • there is one walk;
    • a deploy with the step off never fails over Cosmos Boost (a missing dags/ makes the empty tarball it always did).
    • Anything else at such a path, links included, ships untouched when the step is off.
  • Always, in a generated image: pkg/imagebuild's project copy, which carries dags/ since Carry the project's files in the image a deploy or astro package generates #2302/Keep secrets out of shipped images, and deploy to DAG-deploy-off Deployments #2306, leaves the same files out of the copy, the survey and the tag digest.
  • Declared Dockerfile: the build is warned, not refused. The warning names the old sidecars in its context and says to delete them.
  • One definition of the sidecar directory, file names and producer marker, in pkg/airflowrt, which both the root module and pkg/imagebuild already require. precompute uses those constants.
  • astro dbt cleanup is now a removed-command stub (cliout.RemovedCommand, the Guard removed 1.x commands in CI, and give bundle create/update/delete -o json #2291 pattern). It is a usage error, exit 2, and under -o json the one error object. It says v2 no longer writes Cosmos Boost files into the project and leaves out old ones from every bundle and generated image. It also says to delete any old ones by hand, since a local Airflow running the plugin, or a declared Dockerfile build, may still read them. It still satisfies TestEveryV1CommandStillRunsOrSaysWhatReplacedIt.
  • Removed as dead code: cosmosboost.Cleanup/EnsureClean/BestEffortPreDeploy/PreDeploy, precompute.Cleanup and its report, the on-disk writers, dbtCleanupJSON and its golden cmd/astro/testdata/schema/dbt-cleanup.json. Astro Desktop does not use pkg/cosmosboost.
  • Bundle writing:
    • UploadBundle streams tar into gzip into one file, in a temporary directory of its own. That directory is never the one being bundled, so the tarball cannot carry itself, which --project-path . used to allow.
    • The tar footer, the gzip stream and the file are each closed with their errors checked, so a full disk fails the deploy.
    • Entry names are computed with filepath.Rel, so a source of . names .astro/... and other dotfiles correctly.

Plugin contract: unchanged

Same paths (<unit>/.astro/dbt_metadata.json, <unit>/.astro/manifest.slim.json), same JSON, same hash algorithms. The project hash already excludes .astro at any depth, so whether a stale sidecar sits in the tree does not change it. When a DAG deploy prepends dags/, the sidecars sit under it like every other file.

Tests

  • pkg/cosmosboost, through a real tarball:
    • enabled output matches precompute.Run byte for byte, and the tree snapshot is unchanged;
    • stale files are left out when enabled and when disabled, including one under logs/ and orphans;
    • a foreign file at a written path is refused before "complete"; foreign files elsewhere ship (non-dbt manifest.json, dbt_packages/, logs/, slim off);
    • with the feature off a link ships as a link, and with it on a link or a directory is replaced;
    • a missing root with the feature on and off, and the best-effort failure.
  • pkg/cosmosboost/precompute: Run writes nothing, a file named .astro fails the unit, and whatever sits at an artifact path is replaced. The existing hash and slim tests are kept.
  • pkg/airflowrt: the predicate, including duplicate keys and malformed input.
  • pkg/imagebuild: the generated image leaves stale sidecars out of the survey, copy and digest; a declared survey names them.
  • internal/shipcheck: the declared-Dockerfile warning.
  • pkg/fileutil: TarGz with the overlay, source ., a Skip error, and a compressed stream that fails at close.
  • internal/platform/astro/deploy: UploadBundle / DeployBundle decode the upload and check:
    • the sidecars are in it and the tree is unchanged;
    • stale files are left out, and foreign files are handled per setting;
    • a missing dags/ with the feature off and on;
    • --project-path . from the working directory gives only the fresh sidecar and no tarball inside.
  • cmd/astro: the dbt cleanup stub in text and -o json, and it touches nothing.

Notes

…t, and retire astro dbt cleanup

The pre-deploy step produces its .astro/dbt_metadata.json and
.astro/manifest.slim.json in memory, and the bundle tarball carries
them at the same paths with the same bytes, through a TarOverlay on
fileutil.Tar. Nothing is written into the user's tree.

Every bundle deploy leaves out the sidecars an earlier CLI wrote into
the tree (producer marker "astro"), enabled or not, so a stale one
never ships. One from an unrecognized producer still stops an enabled
deploy, and ships untouched when the step is off.

With nothing left to clean, astro dbt cleanup becomes a removed-command
stub, and its cleanup code, json shape and golden go.

Co-Authored-By: Claude <noreply@anthropic.com>
@schnie
schnie requested a review from a team as a code owner October 14, 2026 16:11
@coveralls-official

coveralls-official Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Coverage Report for CI Build 38606515661

Coverage decreased (-0.04%) to 57.861%

Details

  • Coverage decreased (-0.04%) from the base build.
  • Patch coverage: 21 uncovered changes across 4 files (223 of 244 lines covered, 91.39%).
  • 4 coverage regressions across 3 files.

Uncovered Changes

File Changed Covered %
pkg/fileutil/files.go 95 85 89.47%
pkg/cosmosboost/predeploy.go 60 54 90.0%
internal/platform/astro/deploy/bundle.go 16 12 75.0%
pkg/cosmosboost/precompute/precompute.go 46 45 97.83%
Total (10 files) 244 223 91.39%

Coverage Regressions

4 previously-covered lines in 3 files lost coverage.

File Lines Losing Coverage Coverage
pkg/cosmosboost/predeploy.go 2 89.87%
internal/platform/astro/deploy/bundle.go 1 76.3%
pkg/cosmosboost/precompute/precompute.go 1 98.81%

Coverage Stats

Coverage Status
Relevant Lines: 69361
Covered Lines: 40133
Line Coverage: 57.86%
Coverage Strength: 276.33 hits per line

💛 - Coveralls

schnie and others added 4 commits October 14, 2026 12:33
…t of generated images

The bundle judges each .astro/dbt_metadata.json and manifest.slim.json
by its producer marker inside Tar's own walk (TarOverlay.Skip), rather
than in a separate pre-scan: what it leaves out is exactly what the
tarball would have carried (one under logs/ too), and a deploy with the
step off never fails over Cosmos Boost - a missing dags/ makes the
empty tarball it always did. A foreign file still refuses an enabled
deploy, now even where a fresh sidecar would replace it.

The predicate lives in pkg/airflowrt, a leaf both the root module and
pkg/imagebuild already require. A generated image's project copy (and
its survey and tag digest) leaves the same files out; a declared
Dockerfile's context carrying them is warned about, naming them.

Tar names entries with filepath.Rel, so a source of "." (astro dbt
deploy --project-path .) names .astro/ and other dotfiles right. A
directory or link where a sidecar goes fails that unit instead of
colliding with it in the bundle. The dbt cleanup stub says what v2
does now, and why old files are still worth deleting by hand.

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
…decar paths, and keep the tarball out of the bundle

UploadBundle writes the tarball to a temporary directory of its own. It
used to land in the working directory, which under astro dbt deploy
--project-path . is the directory being bundled, so it could carry
itself.

Tar asks the overlay's Skip about every entry, links and directories
too, and anything at a sidecar's path that is not a regular file is
left out with a warning. With the step on, a link there is replaced by
the fresh sidecar; a directory cannot be, so that unit fails. A
generated image leaves them out the same way, and a declared
Dockerfile's survey names them for its warning.

The foreign-producer refusal now covers only the .astro/ of a unit the
step stamps, where the plugin reads, and runs on those few paths before
anything is hashed, so it comes before any "step complete". One under
dbt_packages/ or logs/ is the project's file and ships.

precompute takes the sidecar directory, names and producer from
airflowrt, and the marker check stream-decodes only the marker. Run
splits into Discover and Units.Run so the check sees the units first.

Co-Authored-By: Claude <noreply@anthropic.com>
…e gzipped file

The foreign-producer refusal is decided from the paths this deploy
actually writes a fresh sidecar to, after the step runs and before it
reports complete; a foreign file anywhere else ships. That drops the
separate pre-hash check and the Discover/SidecarDirs split.

With the step off, only regular files an Astro CLI wrote are left out;
links and everything else at a sidecar path ship as they are, in the
bundle and in a generated image. With it on, whatever is at an
artifact's path, a link or a directory too, is left out for the fresh
sidecar; a unit fails only when its .astro is not a directory.

The producer check goes back to unmarshaling the bytes already read.

UploadBundle streams tar into gzip into one file (fileutil.TarGz) and
checks every close, so a full disk fails the deploy instead of
uploading a truncated bundle.

Co-Authored-By: Claude <noreply@anthropic.com>
@schnie
schnie merged commit 10a721d into v2 Oct 14, 2026
6 of 7 checks passed
@schnie
schnie deleted the cosmos-boost-in-bundle branch October 14, 2026 18:53
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