Add comprehensive test coverage for utils and cmd packages - #32
Merged
Conversation
Part of Phase T2 in docs/testing-plan.md. Covers ParseVersionFileJson,
ExtractVersion, HashString, GenerateDockerImageName and
RemoveEmptyStringsFromArray, none of which had any coverage.
These pin current behaviour rather than change it, including the edges the
plan records as findings: ExtractVersion yields "v" for a version file of {}
and "vv1.0.0" for {"version":"v1.0.0"}, and RemoveEmptyStringsFromArray drops
"" but keeps " ".
Phase T2 is still in progress; the remaining hashing and dockerignore tests
follow in a later commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tn4Aqbe88wWU6a5njxB8dA
Covers the rest of Phase T2 in docs/testing-plan.md: HashWatchFiles, HashWatchDirectories, ReadDockerignore, DetectBuildx and parseBuildxVersion. Pins the contracts the plan calls load-bearing: HashWatchFiles and HashWatchDirectories both return "" for an empty list, so a user who never adopts the flags sees no change to cache identity, and DetectBuildx reports every failure mode as (false, "", nil) rather than an error, leaving ResolveBuilder to decide when that is fatal. ReadDockerignore's exclude patterns are asserted to land after the file's, so a negation passed via --exclude can re-include a file the .dockerignore excluded. Also pins the in-place sort in HashWatchDirectories, which mutates the caller's slice, as a documented finding rather than changing it here. DetectBuildx is driven through a fake docker shim on PATH, so it needs neither docker nor buildx to run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tn4Aqbe88wWU6a5njxB8dA
Phase T3 of docs/testing-plan.md. BuildImageBuildx was at zero coverage despite carrying every rule in the "Subprocess credentials (buildx)" section of CLAUDE.md. Drives the function against a fake docker shim on PATH that records its argv, environment and working directory. Asserts that DOCKER_CONFIG is set on the subprocess environment only and never on dockem's own, that a pre-existing DOCKER_CONFIG is stripped rather than duplicated, that every other parent environment variable is passed through (which is what makes --secret id=x,env=VAR work), that cmd.Dir is never set, that the throwaway config directory is removed even when the build exits non-zero, and that subprocess output lands on stderr so stdout stays clean for --output-format=json. The password is checked against argv, BuildLog and BuildResult with a sentinel value, so a future change that leaks it into any of the three fails here. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tn4Aqbe88wWU6a5njxB8dA
…rift Phase T0 of docs/testing-plan.md. Adds a Repo Hygiene workflow asserting no plan.md exists in the repository root, case-insensitively, so planning documents stay in docs/ and scratch state cannot reach develop or main. It runs on the same triggers as the unit test workflow and is kept separate from it to stay cheap and readable. Adds two source-reading guards in the spirit of the existing cache-hash guards. The first fails if fmt.Print* or a direct os.Stdout write appears in any non-test file outside write_build_output.go, enforcing the LogInfo/LogWarn/LogError convention that keeps stdout carrying nothing but the JSON result. The second fails if a flag registered in cli/cmd/build.go is missing from the README, enforcing the documented convention that the two stay in sync. This is the first test file in the cmd package. Both guards were verified to fail on an injected violation before landing; cobra's auto-generated --version flag is carried as a documented exception rather than by editing the README. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tn4Aqbe88wWU6a5njxB8dA
T0, T2 and T3 have landed. Coverage on a non-registry run is now 52.6% for utils (from 38.2%) and 33.8% for cmd (from zero). One T0 item is deliberately left open: confirming the root plan.md guard actually goes red in real CI needs a scratch-branch push to observe, which cannot be done from a local run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tn4Aqbe88wWU6a5njxB8dA
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.
Summary
This PR implements Phase T0, T2, and T3 of the testing plan outlined in
docs/testing-plan.md, adding extensive test coverage for theutilsandcmdpackages. The changes include 13 new test files covering previously untested functions and adding CI hygiene guards.Key Changes
New test files for
utilspackage:build_image_buildx_subprocess_test.go— 580 lines of subprocess integration tests using a fakedockershim to verify argument assembly, environment variable handling, credential isolation, and output streaminghash_watch_directories_test.go— Tests for directory hashing with exclusion patternshash_watch_files_test.go— Tests for file hashing with order invarianceread_dockerignore_test.go— Tests for.dockerignoreparsing and pattern handlingdetect_buildx_test.go— Tests for buildx detection and version parsingextract_version_test.go— Tests for version file extractionhash_string_test.go— Tests for SHA256 hashing with known vectorsgenerate_docker_image_name_test.go— Tests for image name generationparse_version_file_json_test.go— Tests for JSON version parsingremove_empty_strings_from_array_test.go— Tests for array filteringstdout_purity_test.go— Source-reading guard ensuring stdout remains pure outsidewrite_build_output.goNew test file for
cmdpackage:readme_flag_coverage_test.go— Mechanical enforcement that every build flag is documented in README.mdCI hygiene:
.github/workflows/hygiene.yaml— New workflow that asserts noplan.mdexists in the repository root (planning documents belong indocs/)Documentation updates:
docs/testing-plan.md— Updated coverage percentages (utils: 38.2% → 52.6%, cmd: 0.0% → 33.8%) and marked completed phasesNotable Implementation Details
build_image_buildx_subprocess_test.gouse a POSIX shell script fakedockerexecutable to record argv, environment, and working directory without touching a real Docker daemon or registrywrite_build_output.gowrites to stdouthttps://claude.ai/code/session_01Tn4Aqbe88wWU6a5njxB8dA