Prepare ReleaseKit hosted-page delivery
This commit is contained in:
@@ -423,6 +423,7 @@ func writeDeliveryReceipt(t *testing.T, repository string, settings cli.BuildSet
|
||||
|
||||
type deliveryServerState struct {
|
||||
commit string
|
||||
product string
|
||||
remoteCommit string
|
||||
apiRequests int
|
||||
pageExists bool
|
||||
@@ -537,7 +538,11 @@ func newDeliveryServer(t *testing.T, state *deliveryServerState) *httptest.Serve
|
||||
|
||||
func writeDeliveryRelease(w http.ResponseWriter, serverURL string, state *deliveryServerState) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"id": 10, "html_url": serverURL + "/releases/10", "tag_name": "v1.2.3", "target_commitish": state.commit, "name": "Example Product v1.2.3", "body": state.noteBody, "draft": false, "prerelease": false})
|
||||
product := state.product
|
||||
if product == "" {
|
||||
product = "Example Product"
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"id": 10, "html_url": serverURL + "/releases/10", "tag_name": "v1.2.3", "target_commitish": state.commit, "name": product + " v1.2.3", "body": state.noteBody, "draft": false, "prerelease": false})
|
||||
}
|
||||
|
||||
func writeDeliveryProfile(t *testing.T, repository string, settings cli.Settings) {
|
||||
|
||||
129
cmd/releasekit/releasekit_delivery_workflow_test.go
Normal file
129
cmd/releasekit/releasekit_delivery_workflow_test.go
Normal file
@@ -0,0 +1,129 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/cmd/releasekit/internal/cli"
|
||||
)
|
||||
|
||||
func TestReleaseKitSourceDeliveryWorkflowFromTaggedCheckout(t *testing.T) {
|
||||
_, sourceFile, _, ok := runtime.Caller(0)
|
||||
if !ok {
|
||||
t.Fatal("locate integration test source")
|
||||
}
|
||||
root := filepath.Clean(filepath.Join(filepath.Dir(sourceFile), "../.."))
|
||||
profile, err := cli.LoadSettings(root, "")
|
||||
if err != nil {
|
||||
t.Fatalf("load ReleaseKit source-only profile: %v", err)
|
||||
}
|
||||
if profile.Build != nil && len(profile.Build.Targets) != 0 {
|
||||
t.Fatalf("ReleaseKit profile declares binary targets: %#v", profile.Build.Targets)
|
||||
}
|
||||
if profile.Delivery == nil || profile.Delivery.BaseURL != "https://gitea.maximumdirect.net" || profile.Delivery.Owner != "eric" || profile.Delivery.Repository != "ReleaseKit" || profile.Delivery.TokenEnv != "RELEASEKIT_GITEA_TOKEN" {
|
||||
t.Fatalf("ReleaseKit delivery profile = %#v", profile.Delivery)
|
||||
}
|
||||
repository := filepath.Join(t.TempDir(), "tagged ReleaseKit")
|
||||
clone := exec.Command("git", "clone", "--local", "--no-hardlinks", root, repository)
|
||||
if output, err := clone.CombinedOutput(); err != nil {
|
||||
t.Fatalf("clone ReleaseKit source: %v\n%s", err, output)
|
||||
}
|
||||
cliGitRun(t, repository, "config", "user.name", "ReleaseKit Test")
|
||||
cliGitRun(t, repository, "config", "user.email", "releasekit@example.test")
|
||||
|
||||
const version = "v1.2.3"
|
||||
note := "# ReleaseKit v1.2.3\n\nSource-only delivery fixture.\n\n" +
|
||||
"[COPYRIGHT](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v1.2.3/COPYRIGHT) |\n" +
|
||||
"[LICENSE](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v1.2.3/LICENSE) |\n" +
|
||||
"[ATTRIBUTION](https://gitea.maximumdirect.net/eric/ReleaseKit/src/tag/v1.2.3/docs/oss/attribution.md)\n"
|
||||
notePath := filepath.Join(repository, "docs", "releases", version+".md")
|
||||
if err := os.MkdirAll(filepath.Dir(notePath), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(notePath, []byte(note), 0o600); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ignore, err := os.OpenFile(filepath.Join(repository, ".gitignore"), os.O_APPEND|os.O_WRONLY, 0)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := ignore.WriteString("\n/.releasekit/\n"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := ignore.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cliGitRun(t, repository, "add", "docs/releases/"+version+".md", ".gitignore")
|
||||
cliGitRun(t, repository, "commit", "-m", "prepare source-only delivery")
|
||||
|
||||
state := &deliveryServerState{product: "ReleaseKit"}
|
||||
server := newDeliveryServer(t, state)
|
||||
defer server.Close()
|
||||
writeDeliveryProfile(t, repository, cli.Settings{
|
||||
Product: "ReleaseKit",
|
||||
Delivery: &cli.DeliverySettings{BaseURL: server.URL, Owner: "owner", Repository: "example"},
|
||||
})
|
||||
state.commit = cliGitOutput(t, repository, "rev-parse", "HEAD")
|
||||
cliGitRun(t, repository, "tag", "-a", version, "-m", "ReleaseKit v1.2.3")
|
||||
|
||||
remote := filepath.Join(t.TempDir(), "origin.git")
|
||||
initRemote := exec.Command("git", "init", "--bare", remote)
|
||||
if output, err := initRemote.CombinedOutput(); err != nil {
|
||||
t.Fatalf("initialize local delivery remote: %v\n%s", err, output)
|
||||
}
|
||||
cliGitRun(t, repository, "remote", "set-url", "origin", remote)
|
||||
cliGitRun(t, repository, "push", "origin", "HEAD:refs/heads/main", "refs/tags/"+version)
|
||||
|
||||
// Match the maintained workflow: fetch and bind the tag, then build the
|
||||
// executable from that detached tagged checkout before page-only delivery.
|
||||
cliGitRun(t, repository, "fetch", "origin", "refs/tags/"+version+":refs/tags/"+version)
|
||||
if got := cliGitOutput(t, repository, "rev-parse", "refs/tags/"+version+"^{commit}"); got != state.commit {
|
||||
t.Fatalf("fetched tag commit = %s, want %s", got, state.commit)
|
||||
}
|
||||
cliGitRun(t, repository, "checkout", "--detach", state.commit)
|
||||
tool := filepath.Join(repository, ".releasekit", "bin", "releasekit")
|
||||
if err := os.MkdirAll(filepath.Dir(tool), 0o700); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
build := exec.Command("go", "build", "-o", tool, "./cmd/releasekit")
|
||||
build.Dir = repository
|
||||
build.Env = append(os.Environ(), "GOTOOLCHAIN=local", "GOPROXY=off", "GOSUMDB=off")
|
||||
if output, err := build.CombinedOutput(); err != nil {
|
||||
t.Fatalf("build CLI from tagged checkout: %v\n%s", err, output)
|
||||
}
|
||||
|
||||
state.remoteCommit = strings.Repeat("f", 40)
|
||||
failure := exec.Command(tool, "deliver", "--repo", repository, version)
|
||||
failure.Dir = repository
|
||||
failure.Env = append(os.Environ(), "RELEASEKIT_GITEA_TOKEN=fixture-token")
|
||||
if output, err := failure.CombinedOutput(); err == nil {
|
||||
t.Fatalf("delivery with a mismatched hosted tag succeeded: %s", output)
|
||||
}
|
||||
if state.releaseCreates != 0 || cliGitOutput(t, repository, "rev-parse", "refs/tags/"+version+"^{commit}") != state.commit {
|
||||
t.Fatal("delivery failure changed hosted release state or source tag")
|
||||
}
|
||||
state.remoteCommit = ""
|
||||
|
||||
for attempt := 0; attempt < 2; attempt++ {
|
||||
output := runWoodpeckerCommand(t, tool, repository, true, "deliver", "--repo", repository, version)
|
||||
if !strings.Contains(output, "state complete") {
|
||||
t.Fatalf("delivery attempt %d output = %q", attempt+1, output)
|
||||
}
|
||||
}
|
||||
if state.releaseCreates != 1 || state.assetUploads != 0 || state.assetListReads != 0 {
|
||||
t.Fatalf("page-only workflow calls = creates:%d uploads:%d asset reads:%d", state.releaseCreates, state.assetUploads, state.assetListReads)
|
||||
}
|
||||
if state.noteBody != note {
|
||||
t.Fatalf("hosted note body = %q, want complete note %q", state.noteBody, note)
|
||||
}
|
||||
if got := cliGitOutput(t, repository, "rev-parse", "refs/tags/"+version+"^{commit}"); got != state.commit {
|
||||
t.Fatalf("source tag moved after delivery: %s, want %s", got, state.commit)
|
||||
}
|
||||
if status := cliGitOutput(t, repository, "status", "--porcelain"); status != "" {
|
||||
t.Fatalf("tagged checkout became dirty after delivery: %s", status)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user