Repository navigation
Conversation
The "not an Astro project" errors from #2283 gave advice that was wrong in several places, and two commands checked for a project they did not need. - EnsureProjectDir accepts the pyproject.toml project astro init writes itself, so its advice to run astro init is true by construction; astro deploy and astro remote deploy drop their own copies of that bypass. - In the home directory neither check suggests astro init (its .astro/config.yaml is the CLI's settings), and astro init refuses the home directory with a usage error unless a DIRECTORY names somewhere else. - In a subdirectory of a project, the error names that project rather than suggesting a second, nested one; astro init inside a project warns on stderr that commands below it now find the new project. - APC deploy --dags accepts a pyproject.toml project: a DAG-only deploy uploads dags/ and builds nothing. - astro remote deploy --image-name skips the project check, as astro deploy --image-name does. - EnsureDockerfileProjectDir checks for the Dockerfile APC builds, and says which of the two files is missing; cmd/apc's var is renamed to match. - The APC advice names a followable path: astro package --tag <image>, then astro deploy --image-name <image>. - The advice lives in named consts the tests assert against. Co-Authored-By: Claude <noreply@anthropic.com>
Coverage Report for CI Build 37884442998Coverage increased (+0.07%) to 57.536%Details
Uncovered Changes
Coverage Regressions2 previously-covered lines in 2 files lost coverage.
Coverage Stats
💛 - Coveralls |
Follow-up review on the project-directory advice: - APC astro deploy --dags runs EnsureProjectDir, so a 1.x project with no Dockerfile can DAG-deploy again, as it could before; image deploys keep the Dockerfile check. - An empty --image-name= no longer skips the project check, on APC deploy and astro remote deploy: the check reads the bound value. - project.IsAstroProject is the one definition of a project, for EnsureProjectDir, its enclosing-project advice and astro init's nested warning. It reads the manifest first, so a .astro that is a file does not refuse a manifest project, and reports a pyproject it cannot read or parse as an error rather than as a project: an ancestor like that is never named. - config.IsHomeDir (os.SameFile against config.HomePath) is the one home test, run before anything in the directory is read: ~ with a manifest, or a malformed one, is refused. astro init uses it through Deps.IsHomeDir. - fileutil.NearestDir is the one walk up the tree, skipping ~ and the filesystem root; IsWithinProjectDir and isWithinManifestProject use it, and project.Enclosing is gone. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
- A pyproject.toml that does not parse fails the project check with its own parse error, not "run astro init": astro deploy and astro remote deploy both show it. - The home directory passes EnsureProjectDir with a manifest that loads (a container whose WORKDIR is $HOME), and is refused otherwise; astro init still refuses it. - astro deploy's PreRunE reads --image-name's value, as the other two do. - The dbt and non-DAG bundle containment walk counts projects with project.IsAstroProject, so a root pyproject.toml that does not parse no longer stops them. - The 1.x marker test lives once, project.HasLegacyConfig, which config.IsProjectDir calls; it never counts the home directory's .astro/config.yaml, so no caller can. NewDeps sets IsHomeDir. - config.IsHomeDir reads HomePath once per value, and IsWithinProjectDir asks it once per level. - fileutil.NearestReadableDir replaces the two readable adapters and their nolint directives. Co-Authored-By: Claude <noreply@anthropic.com>
…ile as no project One rule replaces the home-directory special cases: a directory is an Astro project when it has a [tool.astro] manifest or a 1.x .astro/config.yaml, and the CLI's own settings file, wherever ASTRO_HOME puts it, is never that .astro/config.yaml (config.IsSettingsFile, compared by path against HomeConfigFile, and against ~/.astro/config.yaml, where the settings live without ASTRO_HOME and where 1.x keeps its own: under ASTRO_HOME that file would otherwise put everything below ~ inside a 1.x project). The walks no longer skip the home directory, so a project there is named as the project above, refuses a dbt project or a non-DAG bundle inside it, and draws init's nested warning; a directory holding only the settings is no project, home or ASTRO_HOME alike. In the home directory, a manifest that fails validation passes the check and deploy reports it; with no project there the home advice stays. astro init refuses only to make a new project in ~: one already there is init's to re-run, as anywhere. A pyproject.toml that exists and cannot be read is reported as the read error, not with advice to run astro init. A subdirectory whose own pyproject.toml does not parse, inside a project, is told about that project first, and the parse error after it. Gone: fileutil.IsHomeDir, SamePathAs, the walks' skip argument, the home cache, manifestLoads, verifyFailed and NewDeps' IsHomeDir default. Co-Authored-By: Claude <noreply@anthropic.com>
Member
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #2283, fixing what review found in the "not an Astro project" advice it added. The first commit fixes the first review round, the second and third a second round, the fourth a third round, and the fifth a final round. Where rounds disagree, the later round is what the code does now: the fifth replaced every home-directory special case with the one rule below, so read that first.
The rule (6ce97ec)
The home directory is an ordinary directory, and the CLI's settings file is never a project's.
[tool.astro], valid or not, or a 1.x.astro/config.yaml. That isproject.IsAstroProject, the same test in every directory,~included. No walk skips~, and nothing overrides the answer there..astro/config.yamlthat is the CLI's own settings file is not a 1.x marker.config.IsSettingsFileis the one definition. It compares by path (fileutil.SamePath) againstHomeConfigFile, whereverASTRO_HOMEputs it, and against~/.astro/config.yaml, where the settings live withoutASTRO_HOMEand where 1.x keeps its own. The second path is there because a manual run showed what happens without it: underASTRO_HOME, a~/.astro/config.yamlbecame a 1.x project and put every directory below~inside it. v2 always excluded that file.internal/projectcannot import config/, soIsAstroProjectandHasLegacyConfigtake the settings test as an argument.config.IsAstroProjectandconfig.IsProjectDirpassIsSettingsFile.astro initgets it throughDeps.IsSettingsFile, which the root wires.What follows from it:
~is a project. It refuses a dbt project or a non-DAG bundle inside it. It drawsastro init sub's nested warning. From~/dags, the advice names~.~with only the settings is no project. It is refused withHomeDirAdvice, as before. APC never takes the settings for a 1.x project.~with a manifest that fails validation passes the check, as anywhere.astro deploythen reports the validation error.ASTRO_HOME=/x:/xis not a project, and nothing below it is inside one because of the settings.astro initin~refuses only to make a new project there. A~that is already a project goes on to init, which answers as it does for any project (ErrAlreadyAstroProjectfor a manifest).Also in this round:
verifyFailedis gone.errors.As-able). With no enclosing project, the parse error is returned as before..astro/config.yamlexists.Removed:
fileutil.IsHomeDir,fileutil.SamePathAs, the walks'skipargument,config's home-stat cache,manifestLoads,verifyFailed, andNewDeps'IsHomeDirdefault. The root wiresIsHomeDirandIsSettingsFile; nil means none is known. Non-test code is 44 lines shorter than at bb16383.Superseded by this round: round 1 item 2 (in part) and item 3's "
~never counts", round 2 items D, E (the~skip) and I (skip), and round 3 items 4, 5 and 7.Tests:
~manifest project: dbt and non-DAG bundle containment refused,astro init subfrom~warns, the advice from~/dagsnames~.~with only the settings: refused withHomeDirAdvice, by both checks.~with an invalid manifest: the check passes andastro deployreturns the*manifest.ValidationError.astro initin~: creating is refused, a re-run reaches init.ASTRO_HOME, run through the realinitHome, also through a symlink: neither that directory nor~/.astro/config.yamlis a project.Mutation checks, where each test failed against the mutated code:
HasLegacyConfigignoring the settings test: config, utils, init and project tests failed.IsSettingsFilebuilt fromHomePathinstead ofHomeConfigFile: theASTRO_HOMEcases failed.IsSettingsFilewithout the~/.astro/config.yamlpath: theASTRO_HOMEhome cases in config and utils failed.astro init's re-run allowance removed:TestInitReRunsInAHomeDirectoryProjectfailed.First round (c380e09)
astro deploy --dagsrefused a pyproject.toml project. A DAG-only deploy uploadsdags/from the working directory and builds nothing. (Reworked in round 2, item A.)$HOMEthe advice was to run astro init. Both checks now give a home-directory message (its.astro/config.yamlholds the CLI's settings; change to a project directory).astro initrefuses the home directory with a usage error (exit 2, kindusageunder-o json, nothing written).astro init my-projectrun from~still works. The new code is incmd/local/initguard.go.initcmd.gogains only two calls, to stay clear of Refuse to convert a 1.x project under an APC context, and give the same advice everywhere #2285.~never counts as the enclosing project.astro initinside a project now warns on stderr and still creates the project. I chose a warning over a refusal because a repository can legitimately hold several projects, and commands always find the nearest manifest, so the outer project keeps working from its own root. What changes is which project a command run below the new one acts on, and that is what the warning says.astro remote deploy --image-namestill checked for a project.DeployClientImagewith an image name tags and pushes it without building anything. The check is now skipped when an image is named. (The test is on the value now: round 2, item B.)utils.EnsureProjectDir. That makes its "run astro init" advice true by construction. The copies incmd/astro/deploy.goandcmd/astro/remote.goare gone;--image-name,--non-dagsand--dags-pathkeep their own bypasses.EnsureDockerfileProjectDirdid not check for a Dockerfile. It now checks<WorkingPath>/Dockerfile, the fixed pathdeploy.Airflowparses. A.astro/config.yamlwith no Dockerfile gets " has a .astro/config.yaml but no Dockerfile…" instead of a later "failed to parse dockerfile".WorkingPath).astro package --tag <image>, thenastro deploy --image-name <image>.cmd/utils(AstroProjectDirAdvice,APCProjectDirAdvice,APCNoDockerfileAdvice,HomeDirAdvice,EnclosingProjectAdvice). The tests assert against those consts plus a few key tokens.Second round (7e6783a, 105dec5)
A. Regression: APC
astro deploy --dagsrefused a 1.x project with no Dockerfile. The Dockerfile check ran for DAG-only deploys too. The cmd/apc var is back to its v2 name,EnsureProjectDir, and is nowensureDeployProjectDir. That function runsutils.EnsureProjectDirfor--dags, which accepts a manifest or a.astro/config.yaml, andutils.EnsureDockerfileProjectDirfor everything else. The rename in round 1 is undone, sodeployment_json_test.gomatches v2 again.B. An empty
--image-name=skipped the project check and then built from a directory that is not a project.astro remote deployand APCastro deploynow test the bound value (remoteImageName != "",imageName != "") instead ofChanged.C. A manifest project whose
.astrois a file (ENOTDIR) or unreadable was refused.project.IsAstroProjectreads the manifest first. A pyproject.toml carrying[tool.astro], valid or not, makes the directory a project whatever state.astrois in.D.
~passed when~/pyproject.tomlhad[tool.astro], or could not be read.HasManifestcounts read and parse errors as a manifest. The home check now runs before anything in the directory is read, so~is always refused withHomeDirAdvice. (Narrowed in round 3, item 4: a manifest that loads makes~a project.)E. False nested warnings. A malformed
~/pyproject.tomlor an unreadable ancestor used to produce one. The walk now skips~and the filesystem root. The predicate is strict: a pyproject that cannot be read or parsed is an error, not a project, and a walk treats that as "not a project".F/G. One home test.
config.IsHomeDir(path)compares againstconfig.HomePathwithos.SameFile. When either path cannot be stat'ed, it falls back to comparing the symlink-resolved absolute paths, case-insensitively on Windows.IsProjectDirand bothEnsure*checks use it, and so doesastro initthrough a newDeps.IsHomeDirthatcmd/root.gowires toconfig.IsHomeDir(cmd/local cannot import config/).os.UserHomeDiris no longer used.H. One definition of "the project above".
project.IsAstroProject(a manifest or a.astro/config.yaml) is used byEnsureProjectDir, its enclosing advice andastro init's nested warning. Init and deploy now agree:config.yamland no Dockerfile is named by both..astrois named by neither.APC's advice uses its own Dockerfile-project predicate, consistently.
I. One walk.
fileutil.NearestDir(dir, skip, match)checks the directory and then each one above it. It passes over~(viaskip) and the filesystem root, and returns the first error frommatch.config.IsWithinProjectDirandcmd/astro'sisWithinManifestProjectdelegate to it.project.Enclosingis deleted. A side effect:IsWithinProjectDirno longer asks about the relative""/C:first path component, which used to resolve against the working directory.J. Each rule is written once.
EnsureProjectDirandEnsureDockerfileProjectDirareensureDir(predicate, advice, …), with the same predicate passed to the enclosing-project advice.Tests cover each item. Two of them were mutation-checked, and the tests failed when the fix was reverted:
ensureDeployProjectDirchanged to always run the Dockerfile check.config.IsHomeDirwas also reverted to a string compare, and the symlink tests failed.Third round (bb16383)
IsAstroProjectreturns the parse error for it, and the check wrapped that in the init advice beforedeploy()could report it.ensureDirnow returns a*manifest.ParseErroras it is:astro deployandastro remote deployboth showparse <dir>/pyproject.toml: …, syntax and type errors alike. (A type error inside[tool.astro]is a validation error, which already counted as a project and reaches the manifest deploy's own report.)astro deploytestedChanged(--image-name). It now testsimageName != ""like the other two, so--image-name=runs the project check.HasManifest.isWithinManifestProjectnow walks withproject.IsAstroProject, so a repository-root pyproject.toml that does not parse (and so shows no[tool.astro]) no longer refuses a dbt project below it.$HOMEwas refused even with a valid manifest (a container withWORKDIR=$HOME).EnsureProjectDiraccepts~when~/pyproject.tomlloads (manifest.Loadsucceeds), and refuses it withHomeDirAdviceotherwise: no project, a manifest that fails to parse or validate, or only~/.astro/config.yaml. APC's Dockerfile check never accepts~.astro initstill refuses to scaffold into~.HomeDirAdvicenow reads "This is your home directory, and its .astro/config.yaml holds the CLI's own settings, not a project's. Change to a project directory".Deps.IsHomeDirlet~/.astro/config.yamlcount as a project. The 1.x marker check itself now ignores the home directory's.astro/config.yaml, so no caller can get this wrong.NewDepsalso setsIsHomeDir(tofileutil.IsHomeDir), and the root still replaces it withconfig.IsHomeDir.project.HasLegacyConfigis now the only check for.astro/config.yaml(LegacyConfigDir/LegacyConfigFile).config.IsProjectDirandconfig.IsWithinProjectDircall it. config/ may import internal/project; archlint forbids only the reverse. One side effect: a.astrothat is a file (ENOTDIR) is now "not a project" inconfig.IsProjectDirtoo, where it used to be an "error ambiguous".config.IsHomeDirkeeps afileutil.SamePathAs(HomePath)matcher, rebuilt whenHomePathchanges, soHomePathis stat'ed once per value.IsWithinProjectDirno longer asks about the home directory twice at each level.HasLegacyConfigasks about the home directory only when the marker is present.readableadapter is gone. It was duplicated and needed three//nolint:errcheck.fileutil.NearestReadableDirreplaces it: amatcherror means "not this one". The advice walk, the init nested warning and the containment walk use it.Tests: a syntax error and a type error each surface as
*manifest.ParseError, throughutils.EnsureProjectDir,astro deploy's PreRunE (with the real check) andastro remote deploy's.astro deploy --image-name=is refused. A dbt project below an unparseable root pyproject deploys. In~: a manifest that loads passes, including through a symlink; a manifest that fails validation, a syntax error, a typo'd[tool.astroand a lone.astro/config.yamlare each refused, and APC refuses all of them.astro initunder a~that holds.astro/config.yamlgives no nested warning, both withNewDeps'IsHomeDirand with none. There are also tests forHasLegacyConfigin the home directory,NearestReadableDirandSamePathAs.Mutation checks, where each test failed against the mutated code:
TestDeployProjectCheckandTestRemoteDeployProjectCheckfailed.HasManifest/IsAstroProject). Every refuse case failed.HasManifest. The new dbt test failed.Checks
These were run at the fifth round (6ce97ec):
go build ./...andGOOS=windows go build ./..., plusGOOS=windows go veton the changed packagesmake testmake test-e2e(tier 0)make lint(no autofix rewrites)make lint-goosmake deadcodeA manual run of the built binary under a temp
HOME,XDG_CACHE_HOMEandASTRO_TELEMETRY_DISABLED=1, which:~with only the settings;astro init subfrom a~project;~manifest;~from~/dags/x.The temp
HOMEsat inside the real one, so a walk that got past it reached the real~/.astro/config.yaml. Under a tempHOMEthat file is neither settings path, so it counts as a 1.x project, as it did in v2. TheASTRO_HOMEcase was therefore checked by the tests, not by the manual run.Merge with the open PRs (at 6ce97ec)
apc-deploy-warn-no-dags, at ac4f4a0):git merge-treeis clean. The merged tree passesgo build ./...,go vetoncmd/...,config,internal/projectandpkg/fileutil, and the tests incmd/utils,cmd/local,cmd/apc,cmd/astro,cmd,config,internal/projectandpkg/fileutil.init-keep-apc-dockerfile, at 8be1cc5):git merge-treeis clean. The merged tree passes the same build, vet and tests.