diff --git a/.woodpecker/verify.yml b/.woodpecker/verify.yml index 92b0ed4..3a8439a 100644 --- a/.woodpecker/verify.yml +++ b/.woodpecker/verify.yml @@ -25,16 +25,9 @@ steps: commands: - go build ./... - documentation-and-examples: - image: golang:1.26 - depends_on: tests - commands: - - go test ./internal/doccheck - - go test ./internal/config -run '^TestExamplesLoadAndValidate$' - cross-build: image: golang:1.26 - depends_on: [race-tests, static-analysis, build, documentation-and-examples] + depends_on: [race-tests, static-analysis, build] commands: - | set -eu diff --git a/docs/development.md b/docs/development.md index 1f56da3..e4bc410 100644 --- a/docs/development.md +++ b/docs/development.md @@ -56,7 +56,7 @@ Maintained development and verification require Go 1.26. Use the official Go | Adapters or external tool contracts | [Adapter Internals](internal/adapters.md) and [Integration Contracts](integrations/README.md) | The internal guide owns adapter composition and mechanics; integration documents own external formats and protocols. | | Manifests, artifacts, workspace paths, or publish behavior | [Manifest Internals](internal/manifest.md), [Artifact Internals](internal/artifacts.md), [Workspace Internals](internal/workspace.md), [Publish Internals](internal/stage-publish.md), and [Operations](operations.md) | These separate implementation state and resolution from operator-visible layout and lifecycle. | | Maintained configuration or input examples | [Configuration](config.md) and [Examples](../examples/README.md) | The reference owns field meanings; the examples directory owns complete copyable files. | -| Preparing, validating, or publishing a release | [Release Policy](policy/release.md) and [Release Procedure](release.md) | Policy owns requirements and exceptions; the procedure owns concrete validation, guarded publication, and optional later inspection. | +| Preparing, validating, or publishing a release | [Release Policy](policy/release.md) and [Release Procedure](release.md) | Policy owns requirements; the procedure owns concrete validation, guarded publication, and optional later inspection. | | Proposed or unimplemented behavior | `docs/roadmap/` | Future work belongs only in roadmap documentation until implemented. | For an existing subsystem, also inspect its focused tests and package-level @@ -64,24 +64,25 @@ contracts before changing behavior. ## Validation -Use focused package tests while iterating. Every pull request and push runs the -following repository-wide checks before it can be accepted: +Use focused package tests while iterating. Push and pull-request CI runs these +repository-wide checks and cross-builds the declared targets: ```sh go test ./... go test -race ./... go vet ./... go build ./... -go test ./internal/doccheck -go test ./internal/config -run '^TestExamplesLoadAndValidate$' ``` -The documentation check verifies local Markdown links and the dependency graph -of the Woodpecker workflows. The configuration check loads every maintained -pipeline and session example. Tag CI independently revalidates the tagged source -before asynchronous asset delivery; it is not a second synchronous release -prerequisite. The normal maintainer entry point is the single publication command -in the [Release Procedure](release.md). +The full suite includes documentation-link and Woodpecker dependency checks +and loads maintained pipeline and session examples. For focused diagnosis, +run `go test ./internal/doccheck` or +`go test ./internal/config -run '^TestExamplesLoadAndValidate$'` directly; +these are available developer tools, not additional CI steps. Tag CI +independently revalidates the tagged source before asynchronous asset delivery; +it is not a second synchronous release prerequisite. The normal maintainer +entry point is the single publication command in the +[Release Procedure](release.md). Woodpecker also runs `go test -race -shuffle=on -count=3 ./...` on its scheduled job to expose ordering and repeatability defects. Current runners cross-compile diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index b6701a3..c918b48 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -310,7 +310,15 @@ unchanged. Adopt metadata only for the actual document revision incorporated. ## Stage 6: Align CI and contributor validation references -Status: Pending. +Status: Complete (2026-09-28). + +Verification: Removed only the redundant push/PR documentation-and-examples +job, with cross-build dependencies repaired. The full suite still exercises +both checks, while focused commands remain documented for developer diagnosis. +Tag CI, scheduled shuffle/race testing, runner images, build targets, and +non-overwrite publication settings remain unchanged. `go test +./internal/doccheck ./internal/releasecheck` and `git diff --check` passed; +manual review found no CI wait or broad-ref publication path. Read .woodpecker/verify.yml, .woodpecker/release.yml, .woodpecker/shuffle.yml, the doccheck workflow graph tests, and docs/development.md. diff --git a/internal/doccheck/doccheck_test.go b/internal/doccheck/doccheck_test.go index 017ecc5..5913762 100644 --- a/internal/doccheck/doccheck_test.go +++ b/internal/doccheck/doccheck_test.go @@ -49,6 +49,33 @@ func TestWoodpeckerWorkflowDependencies(t *testing.T) { } } +func TestVerifyWorkflowUsesFullSuiteWithoutFocusedDuplicates(t *testing.T) { + path := filepath.Join(repositoryRoot(t), ".woodpecker", "verify.yml") + data, err := os.ReadFile(path) + if err != nil { + t.Fatal(err) + } + var workflow woodpeckerWorkflow + if err := yaml.Unmarshal(data, &workflow); err != nil { + t.Fatal(err) + } + tests, ok := workflow.Steps["tests"] + if !ok || !containsWorkflowCommand(tests.Commands, "go test ./...") { + t.Fatalf("verify workflow lacks the full default suite: %#v", tests) + } + for name, step := range workflow.Steps { + commands := strings.Join(step.Commands, "\n") + if strings.Contains(commands, "go test ./internal/doccheck") || strings.Contains(commands, "go test ./internal/config -run") { + t.Errorf("verify step %q repeats tests covered by the full suite", name) + } + } + for _, dependency := range []string{"race-tests", "static-analysis", "build"} { + if !workflowDependsOn(workflow.Steps, "cross-build", dependency, map[string]bool{}) { + t.Errorf("cross-build does not depend on %q", dependency) + } + } +} + func TestReleaseWorkflowRequiresValidation(t *testing.T) { root := repositoryRoot(t) path := filepath.Join(root, ".woodpecker", "release.yml")