diff --git a/cmd/wails-release/integration_test.go b/cmd/wails-release/integration_test.go new file mode 100644 index 0000000..39b40b8 --- /dev/null +++ b/cmd/wails-release/integration_test.go @@ -0,0 +1,117 @@ +package main + +import ( + "context" + "encoding/base64" + "os" + "path/filepath" + "strings" + "testing" +) + +func TestRun_EndToEnd_FakeBinaries(t *testing.T) { + if testing.Short() { + t.Skip("integration test skipped in -short mode") + } + + repoRoot, _ := os.Getwd() // cmd/wails-release + binDir := filepath.Join(repoRoot, "testdata", "bin") + sampleSrc := filepath.Join(repoRoot, "testdata", "sample-app") + + // Copy the sample app to a writable temp dir so the build step can + // drop output into it without mutating testdata. + work := t.TempDir() + copyTree(t, sampleSrc, work) + + record := t.TempDir() + outputs := filepath.Join(record, "outputs") + must(t, os.WriteFile(outputs, nil, 0o600)) + + t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH")) + t.Setenv("RECORD_DIR", record) + t.Setenv("WORK_DIR", work) + t.Setenv("GITHUB_OUTPUT", outputs) + t.Setenv("GITHUB_REF", "refs/tags/v1.2.3") + t.Setenv("GITHUB_SHA", "0123456789abcdef") + + for k, v := range map[string]string{ + "INPUT_WORKING_DIRECTORY": work, + "INPUT_DEVELOPER_ID_CERT_BASE64": base64.StdEncoding.EncodeToString([]byte("not-a-real-p12")), + "INPUT_DEVELOPER_ID_CERT_PASSWORD": "x", + "INPUT_NOTARIZATION_METHOD": "api-key", + "INPUT_NOTARIZATION_API_KEY_BASE64": base64.StdEncoding.EncodeToString([]byte("not-a-real-p8")), + "INPUT_NOTARIZATION_API_KEY_ID": "K", + "INPUT_NOTARIZATION_API_ISSUER_ID": "I", + } { + t.Setenv(k, v) + } + + if err := run(context.Background()); err != nil { + t.Fatalf("run: %v", err) + } + + // Each external command must have been called. + for _, name := range []string{"wails.log", "security.log", "codesign.log", "ditto.log", "xcrun.log"} { + path := filepath.Join(record, name) + b, err := os.ReadFile(path) + if err != nil { + t.Fatalf("expected %s, got error: %v", name, err) + } + if len(b) == 0 { + t.Fatalf("%s was empty", name) + } + } + + // Outputs file should contain version=1.2.3. + out, err := os.ReadFile(outputs) + if err != nil { + t.Fatalf("read outputs: %v", err) + } + if !strings.Contains(string(out), "version=1.2.3") { + t.Fatalf("expected version=1.2.3 in outputs, got %q", out) + } + if !strings.Contains(string(out), "app-name=SampleApp") { + t.Fatalf("expected app-name=SampleApp in outputs, got %q", out) + } + if !strings.Contains(string(out), "artifact-filename=SampleApp-1.2.3.app.zip") { + t.Fatalf("expected artifact-filename in outputs, got %q", out) + } + + // ditto must have been invoked twice (pre-staple + post-staple). + dittoLog, _ := os.ReadFile(filepath.Join(record, "ditto.log")) + if strings.Count(string(dittoLog), "\n") < 2 { + t.Fatalf("expected ditto called at least twice, log:\n%s", dittoLog) + } + + // security delete-keychain must have run during cleanup. + secLog, _ := os.ReadFile(filepath.Join(record, "security.log")) + if !strings.Contains(string(secLog), "delete-keychain") { + t.Fatalf("expected security delete-keychain in cleanup, log:\n%s", secLog) + } +} + +func must(t *testing.T, err error) { + t.Helper() + if err != nil { + t.Fatal(err) + } +} + +func copyTree(t *testing.T, src, dst string) { + t.Helper() + must(t, filepath.Walk(src, func(p string, info os.FileInfo, err error) error { + if err != nil { + return err + } + rel, _ := filepath.Rel(src, p) + out := filepath.Join(dst, rel) + if info.IsDir() { + return os.MkdirAll(out, 0o755) + } + b, err := os.ReadFile(p) + if err != nil { + return err + } + return os.WriteFile(out, b, info.Mode()) + })) +} diff --git a/cmd/wails-release/testdata/bin/codesign b/cmd/wails-release/testdata/bin/codesign new file mode 100755 index 0000000..ba5a99b --- /dev/null +++ b/cmd/wails-release/testdata/bin/codesign @@ -0,0 +1,3 @@ +#!/bin/bash +echo "$0 $*" >> "$RECORD_DIR/codesign.log" +exit 0 diff --git a/cmd/wails-release/testdata/bin/ditto b/cmd/wails-release/testdata/bin/ditto new file mode 100755 index 0000000..cc3e71d --- /dev/null +++ b/cmd/wails-release/testdata/bin/ditto @@ -0,0 +1,7 @@ +#!/bin/bash +echo "$0 $*" >> "$RECORD_DIR/ditto.log" +# Last argument is the output path; create it. +out="${@: -1}" +mkdir -p "$(dirname "$out")" +echo "fake-zip" > "$out" +exit 0 diff --git a/cmd/wails-release/testdata/bin/go b/cmd/wails-release/testdata/bin/go new file mode 100755 index 0000000..4e229f5 --- /dev/null +++ b/cmd/wails-release/testdata/bin/go @@ -0,0 +1,9 @@ +#!/bin/bash +echo "$0 $*" >> "$RECORD_DIR/go.log" +# install: pretend success. +# env GOPATH: print a tmp value (not actually used in the test path). +case "$1" in + install) ;; + env) echo "/tmp" ;; +esac +exit 0 diff --git a/cmd/wails-release/testdata/bin/security b/cmd/wails-release/testdata/bin/security new file mode 100755 index 0000000..074e4ad --- /dev/null +++ b/cmd/wails-release/testdata/bin/security @@ -0,0 +1,6 @@ +#!/bin/bash +echo "$0 $*" >> "$RECORD_DIR/security.log" +if [[ "$1" == "find-identity" ]]; then + echo ' 1) AAAA1111 "Developer ID Application: Acme Inc (TEAM1234)"' +fi +exit 0 diff --git a/cmd/wails-release/testdata/bin/wails b/cmd/wails-release/testdata/bin/wails new file mode 100755 index 0000000..5cec389 --- /dev/null +++ b/cmd/wails-release/testdata/bin/wails @@ -0,0 +1,9 @@ +#!/bin/bash +echo "$0 $*" >> "$RECORD_DIR/wails.log" +case "$1" in + -v) echo "Wails CLI v2.11.0" ;; + build) + mkdir -p "$WORK_DIR/build/bin/SampleApp.app/Contents/MacOS" + touch "$WORK_DIR/build/bin/SampleApp.app/Contents/MacOS/SampleApp" + ;; +esac diff --git a/cmd/wails-release/testdata/bin/xcrun b/cmd/wails-release/testdata/bin/xcrun new file mode 100755 index 0000000..6d3a707 --- /dev/null +++ b/cmd/wails-release/testdata/bin/xcrun @@ -0,0 +1,12 @@ +#!/bin/bash +echo "$0 $*" >> "$RECORD_DIR/xcrun.log" +case "$1" in + notarytool) + case "$2" in + submit) echo '{"id":"sub-1","status":"Accepted"}' ;; + log) echo '{}' ;; + esac + ;; + stapler) ;; +esac +exit 0 diff --git a/cmd/wails-release/testdata/sample-app/go.mod b/cmd/wails-release/testdata/sample-app/go.mod new file mode 100644 index 0000000..a25dd56 --- /dev/null +++ b/cmd/wails-release/testdata/sample-app/go.mod @@ -0,0 +1,5 @@ +module example.com/sample + +go 1.22.0 + +require github.com/wailsapp/wails/v2 v2.11.0 diff --git a/cmd/wails-release/testdata/sample-app/go.sum b/cmd/wails-release/testdata/sample-app/go.sum new file mode 100644 index 0000000..617fb54 --- /dev/null +++ b/cmd/wails-release/testdata/sample-app/go.sum @@ -0,0 +1 @@ +github.com/wailsapp/wails/v2 v2.11.0/go.mod h1:jrf0ZaM6+GBc1wRmXsM8cIvzlg0karYin3erahI4+0k= diff --git a/cmd/wails-release/testdata/sample-app/wails.json b/cmd/wails-release/testdata/sample-app/wails.json new file mode 100644 index 0000000..1ce7029 --- /dev/null +++ b/cmd/wails-release/testdata/sample-app/wails.json @@ -0,0 +1 @@ +{ "name": "SampleApp" }