Prepare self-bootstrap dependencies through normal Go access
This commit is contained in:
@@ -4,12 +4,15 @@ import (
|
|||||||
"archive/zip"
|
"archive/zip"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit/internal/cli"
|
"gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit/internal/cli"
|
||||||
@@ -228,16 +231,52 @@ func TestWoodpeckerSourceDeliveryTemplateSelfBootstraps(t *testing.T) {
|
|||||||
}
|
}
|
||||||
command := strings.ReplaceAll(block, "$${", "${")
|
command := strings.ReplaceAll(block, "$${", "${")
|
||||||
repository := newCLIRepository(t)
|
repository := newCLIRepository(t)
|
||||||
writeRepositoryFile(t, repository, "cmd/releasekit/main.go", "package main\n\nimport (\"fmt\"; \"os\")\n\nfunc main() {\n\tfmt.Println(\"self-bootstrap\")\n\tfmt.Printf(\"tool-args=%q\\n\", os.Args[1:])\n}\n")
|
const dependency = "example.com/releasekit-helper"
|
||||||
cliGitRun(t, repository, "add", "cmd/releasekit/main.go")
|
proxyDir := t.TempDir()
|
||||||
|
writeModuleProxyVersion(t, proxyDir, dependency, "v1.0.0", "module "+dependency+"\n\ngo 1.25.0\n", map[string]string{
|
||||||
|
"helper.go": "package helper\n\nconst Message = \"prepared tool dependency\"\n",
|
||||||
|
})
|
||||||
|
var proxyRequests atomic.Int64
|
||||||
|
files := http.FileServer(http.Dir(proxyDir))
|
||||||
|
proxy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
proxyRequests.Add(1)
|
||||||
|
files.ServeHTTP(w, r)
|
||||||
|
}))
|
||||||
|
defer proxy.Close()
|
||||||
|
writeRepositoryFile(t, repository, "go.mod", "module example.com/cli-candidate\n\ngo 1.25.0\n\nrequire "+dependency+" v1.0.0\n")
|
||||||
|
writeRepositoryFile(t, repository, "cmd/releasekit/main.go", "package main\n\nimport (\"fmt\"; \"os\"; helper \""+dependency+"\")\n\nfunc main() {\n\tfmt.Println(\"self-bootstrap \" + helper.Message)\n\tfmt.Printf(\"tool-args=%q\\n\", os.Args[1:])\n}\n")
|
||||||
|
preparationEnv := map[string]string{
|
||||||
|
"GOPROXY": proxy.URL, "GOSUMDB": "off", "GONOPROXY": "none", "GOPRIVATE": "",
|
||||||
|
"GOWORK": "off", "GOTOOLCHAIN": "local", "GOENV": "off", "GOFLAGS": "-modcacherw",
|
||||||
|
"GOMODCACHE": t.TempDir(),
|
||||||
|
}
|
||||||
|
runWoodpeckerBlock(t, "go mod download "+dependency, repository, preparationEnv)
|
||||||
|
cliGitRun(t, repository, "add", "cmd/releasekit/main.go", "go.mod", "go.sum")
|
||||||
cliGitRun(t, repository, "commit", "-m", "add the self-bootstrapped command")
|
cliGitRun(t, repository, "commit", "-m", "add the self-bootstrapped command")
|
||||||
commit := pushTaggedCLIRepository(t, repository)
|
commit := pushTaggedCLIRepository(t, repository)
|
||||||
goDir, goLog := installGoBootstrapShim(t)
|
goDir, goLog := installGoBootstrapShim(t)
|
||||||
env := templateEnvironment(repository, commit, goDir, goLog)
|
env := templateEnvironment(repository, commit, goDir, goLog)
|
||||||
|
for key, value := range preparationEnv {
|
||||||
|
env[key] = value
|
||||||
|
}
|
||||||
|
env["GOMODCACHE"] = t.TempDir()
|
||||||
|
proxyRequests.Store(0)
|
||||||
|
env["CI_COMMIT_SHA"] = strings.Repeat("0", len(commit))
|
||||||
|
if output, err := executeWoodpeckerBlock(command, repository, env); err == nil {
|
||||||
|
t.Fatalf("wrong commit unexpectedly bootstrapped the tool: %s", output)
|
||||||
|
}
|
||||||
|
assertNoCommands(t, goLog)
|
||||||
|
if proxyRequests.Load() != 0 {
|
||||||
|
t.Fatal("wrong commit reached tool dependency preparation")
|
||||||
|
}
|
||||||
|
env["CI_COMMIT_SHA"] = commit
|
||||||
output := runWoodpeckerBlock(t, command, repository, env)
|
output := runWoodpeckerBlock(t, command, repository, env)
|
||||||
if !strings.Contains(output, "self-bootstrap") || !strings.Contains(output, `"`+commit+`"`) {
|
if !strings.Contains(output, "self-bootstrap prepared tool dependency") || !strings.Contains(output, `"`+commit+`"`) {
|
||||||
t.Fatalf("self-bootstrap output = %q", output)
|
t.Fatalf("self-bootstrap output = %q", output)
|
||||||
}
|
}
|
||||||
|
if proxyRequests.Load() == 0 {
|
||||||
|
t.Fatal("self-bootstrap did not prepare its dependency from the local proxy")
|
||||||
|
}
|
||||||
if !strings.Contains(output, `"ci-deliver"`) || !strings.Contains(output, `"`+repository+`"`) || !strings.Contains(output, `"v1.2.3"`) {
|
if !strings.Contains(output, `"ci-deliver"`) || !strings.Contains(output, `"`+repository+`"`) || !strings.Contains(output, `"v1.2.3"`) {
|
||||||
t.Fatalf("self-bootstrapped command arguments = %q", output)
|
t.Fatalf("self-bootstrapped command arguments = %q", output)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,6 +184,10 @@ the executable separately and invoke the same `ci-deliver` command. For
|
|||||||
ReleaseKit's own source workflow, the maintained
|
ReleaseKit's own source workflow, the maintained
|
||||||
[source-delivery template](../../examples/woodpecker/releasekit-source-delivery.yml)
|
[source-delivery template](../../examples/woodpecker/releasekit-source-delivery.yml)
|
||||||
checks out the tag and self-bootstraps `./cmd/releasekit` into temporary storage.
|
checks out the tag and self-bootstraps `./cmd/releasekit` into temporary storage.
|
||||||
|
Its readonly tool build uses committed module metadata and can fetch missing
|
||||||
|
dependencies through normal Go proxy, private-module, checksum, and cache
|
||||||
|
settings. Tool bootstrap follows tag verification; offline candidate validation
|
||||||
|
and application artifact compilation retain their separate environments.
|
||||||
|
|
||||||
The normal Go module and build caches are sufficient. Cache mounts may be added
|
The normal Go module and build caches are sufficient. Cache mounts may be added
|
||||||
as deployment configuration when they help the runner; they are not needed by
|
as deployment configuration when they help the runner; they are not needed by
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
# ReleaseKit implementation remediation
|
# ReleaseKit implementation remediation
|
||||||
|
|
||||||
Status: One open v0.2.0 finding (9). Findings 1–8 are addressed.
|
Status: All nine findings addressed.
|
||||||
|
|
||||||
The v0.2.0 review covers committed state `edd670e` and the implementation
|
The v0.2.0 review covers committed state `edd670e` and the implementation
|
||||||
commits after `89981ab`, against the [implementation plan](implementation.md),
|
commits after `89981ab`, against the [implementation plan](implementation.md),
|
||||||
[feature roadmap](v0.2.0.md), [model roadmap](model.md), accepted ADRs, and
|
[feature roadmap](v0.2.0.md), [model roadmap](model.md), accepted ADRs, and
|
||||||
applicable repository policies. Both ReleaseKit and Audita had clean worktrees
|
applicable repository policies. Both ReleaseKit and Audita had clean worktrees
|
||||||
when inspected. This review changes only this document.
|
when inspected. The review changed only this document; the resolutions below
|
||||||
|
record subsequent remediation.
|
||||||
|
|
||||||
## Foundation review history
|
## Foundation review history
|
||||||
|
|
||||||
@@ -285,10 +286,10 @@ tool through temporary module metadata. Audita's local wrapper and workflow
|
|||||||
adopt that approach in commit `17421bc`; the inspected declarations preserve
|
adopt that approach in commit `17421bc`; the inspected declarations preserve
|
||||||
its existing dependency version, image, secret name, and release profile.
|
its existing dependency version, image, secret name, and release profile.
|
||||||
|
|
||||||
All ten feature areas are present. The three findings below identify incomplete
|
All ten feature areas are present. The review identified three behavior gaps
|
||||||
behavior within Markdown validation and self-bootstrap. Finding 8 imposes
|
within Markdown validation and self-bootstrap. Finding 8 imposed unrequested
|
||||||
unrequested existence/boundary checks on image alternative text. Finding 9
|
existence/boundary checks on image alternative text. Finding 9 effectively
|
||||||
effectively requires a prepopulated tool module cache. The review found no
|
required a prepopulated tool module cache. The review found no
|
||||||
additional public package, validator-registration framework, universal optional
|
additional public package, validator-registration framework, universal optional
|
||||||
check, arbitrary inspection limit, or change to source-publication completion.
|
check, arbitrary inspection limit, or change to source-publication completion.
|
||||||
|
|
||||||
@@ -371,6 +372,16 @@ real linked images still report missing image sources and missing link targets.
|
|||||||
|
|
||||||
## 9. P1: ReleaseKit's source-delivery bootstrap fails with an empty module cache
|
## 9. P1: ReleaseKit's source-delivery bootstrap fails with an empty module cache
|
||||||
|
|
||||||
|
**Resolution:** Addressed. Self-bootstrap uses normal Go dependency access for
|
||||||
|
its readonly tool build after tag verification. The maintained workflow test
|
||||||
|
starts with an empty module cache and a local HTTP module proxy, builds a tool
|
||||||
|
with an external dependency, and verifies execution, clean tagged source, and
|
||||||
|
temporary-output cleanup. A wrong commit stops before Go or proxy access. The
|
||||||
|
regression failed before the fix and passed afterward. The delivery guide now
|
||||||
|
describes tool dependency access and its separation from offline validation.
|
||||||
|
The uncached offline suite, `go run ./internal/apicheck`, and local documentation
|
||||||
|
link/fragment checks passed after all three fixes.
|
||||||
|
|
||||||
**Owners:** [source-delivery workflow](../../examples/woodpecker/releasekit-source-delivery.yml),
|
**Owners:** [source-delivery workflow](../../examples/woodpecker/releasekit-source-delivery.yml),
|
||||||
lines 27–31; [workflow verification](../../cmd/releasekit/woodpecker_test.go),
|
lines 27–31; [workflow verification](../../cmd/releasekit/woodpecker_test.go),
|
||||||
`TestWoodpeckerSourceDeliveryTemplateSelfBootstraps`; and the
|
`TestWoodpeckerSourceDeliveryTemplateSelfBootstraps`; and the
|
||||||
@@ -415,5 +426,5 @@ delivery tests retain ownership of hosted page behavior.
|
|||||||
Goldmark's renderer confirmed the alternative-text semantics. A separate
|
Goldmark's renderer confirmed the alternative-text semantics. A separate
|
||||||
temporary empty module cache reproduced finding 9. These probes are review
|
temporary empty module cache reproduced finding 9. These probes are review
|
||||||
evidence; production code and the committed test suite remain unchanged.
|
evidence; production code and the committed test suite remain unchanged.
|
||||||
- Existing tests pass but omit these cases. The required fixes remain open;
|
- Existing tests passed but omitted these cases at review time. The resolutions
|
||||||
their remediation and regression coverage are subsequent work.
|
above record completed fixes and regression coverage.
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ steps:
|
|||||||
trap 'rm -rf "$${bootstrap_dir}"' EXIT
|
trap 'rm -rf "$${bootstrap_dir}"' EXIT
|
||||||
export GOWORK=off
|
export GOWORK=off
|
||||||
export GOTOOLCHAIN=local
|
export GOTOOLCHAIN=local
|
||||||
export GOPROXY=off
|
|
||||||
export GOSUMDB=off
|
|
||||||
go build -mod=readonly -o "$${bootstrap_dir}/releasekit" ./cmd/releasekit
|
go build -mod=readonly -o "$${bootstrap_dir}/releasekit" ./cmd/releasekit
|
||||||
"$${bootstrap_dir}/releasekit" ci-deliver \
|
"$${bootstrap_dir}/releasekit" ci-deliver \
|
||||||
--repo "$${CI_WORKSPACE}" \
|
--repo "$${CI_WORKSPACE}" \
|
||||||
|
|||||||
Reference in New Issue
Block a user