Merge pull request #113 from bnema/feat/linux-arm64-prebuilt-binary
build: publish Linux ARM64 pre-built binary
8 files · +171 -11
M .github/workflows/ci.yml +10 -0
| @@ -36,6 +36,16 @@ jobs: | |||
| 36 | 36 | run: make lint | |
| 37 | 37 | - name: Test | |
| 38 | 38 | run: make test | |
| 39 | + | - name: Test installer | |
| 40 | + | if: matrix.os == 'ubuntu-latest' | |
| 41 | + | run: make test-installer | |
| 42 | + | - name: Cross-compile linux/arm64 | |
| 43 | + | if: matrix.os == 'ubuntu-latest' | |
| 44 | + | env: | |
| 45 | + | CGO_ENABLED: 0 | |
| 46 | + | GOARCH: arm64 | |
| 47 | + | GOOS: linux | |
| 48 | + | run: go build ./... | |
| 39 | 49 | - name: Cross-compile darwin/arm64 | |
| 40 | 50 | if: matrix.os == 'ubuntu-latest' | |
| 41 | 51 | env: | |
| @@ -36,6 +36,16 @@ jobs: | |||||
| 36 | run: make lint | 36 | run: make lint | ||
| 37 | - name: Test | 37 | - name: Test | ||
| 38 | run: make test | 38 | run: make test | ||
| 39 | + | - name: Test installer | |||
| 40 | + | if: matrix.os == 'ubuntu-latest' | |||
| 41 | + | run: make test-installer | |||
| 42 | + | - name: Cross-compile linux/arm64 | |||
| 43 | + | if: matrix.os == 'ubuntu-latest' | |||
| 44 | + | env: | |||
| 45 | + | CGO_ENABLED: 0 | |||
| 46 | + | GOARCH: arm64 | |||
| 47 | + | GOOS: linux | |||
| 48 | + | run: go build ./... | |||
| 39 | - name: Cross-compile darwin/arm64 | 49 | - name: Cross-compile darwin/arm64 | ||
| 40 | if: matrix.os == 'ubuntu-latest' | 50 | if: matrix.os == 'ubuntu-latest' | ||
| 41 | env: | 51 | env: | ||
M .goreleaser.yaml +2 -4
| @@ -19,8 +19,6 @@ builds: | |||
| 19 | 19 | - amd64 | |
| 20 | 20 | - arm64 | |
| 21 | 21 | ignore: | |
| 22 | - | - goos: linux | |
| 23 | - | goarch: arm64 | |
| 24 | 22 | - goos: darwin | |
| 25 | 23 | goarch: amd64 | |
| 26 | 24 | ldflags: | |
| @@ -32,7 +30,7 @@ builds: | |||
| 32 | 30 | archives: | |
| 33 | 31 | - id: default | |
| 34 | 32 | # Contract consumed by install.sh and the AUR package block: | |
| 35 | - | # vev_linux_x86_64.tar.gz / vev_darwin_arm64.tar.gz | |
| 33 | + | # vev_linux_x86_64.tar.gz / vev_linux_arm64.tar.gz / vev_darwin_arm64.tar.gz | |
| 36 | 34 | name_template: >- | |
| 37 | 35 | {{ .ProjectName }}_{{ .Os }}_{{ if eq .Arch "amd64" }}x86_64{{ else }}{{ .Arch }}{{ end }} | |
| 38 | 36 | formats: ['tar.gz'] | |
| @@ -89,7 +87,7 @@ release: | |||
| 89 | 87 | ||
| 90 | 88 | ## Install | |
| 91 | 89 | ||
| 92 | - | ### Script (Linux x86_64, macOS arm64) | |
| 90 | + | ### Script (Linux x86_64/arm64, macOS arm64) | |
| 93 | 91 | ```sh | |
| 94 | 92 | curl -fsSL https://raw.githubusercontent.com/bnema/vev/{{ .Tag }}/install.sh | VEV_VERSION={{ .Tag }} sh | |
| 95 | 93 | ``` | |
| @@ -19,8 +19,6 @@ builds: | |||||
| 19 | - amd64 | 19 | - amd64 | ||
| 20 | - arm64 | 20 | - arm64 | ||
| 21 | ignore: | 21 | ignore: | ||
| 22 | - | - goos: linux | |||
| 23 | - | goarch: arm64 | |||
| 24 | - goos: darwin | 22 | - goos: darwin | ||
| 25 | goarch: amd64 | 23 | goarch: amd64 | ||
| 26 | ldflags: | 24 | ldflags: | ||
| @@ -32,7 +30,7 @@ builds: | |||||
| 32 | archives: | 30 | archives: | ||
| 33 | - id: default | 31 | - id: default | ||
| 34 | # Contract consumed by install.sh and the AUR package block: | 32 | # Contract consumed by install.sh and the AUR package block: | ||
| 35 | - | # vev_linux_x86_64.tar.gz / vev_darwin_arm64.tar.gz | 33 | + | # vev_linux_x86_64.tar.gz / vev_linux_arm64.tar.gz / vev_darwin_arm64.tar.gz |
| 36 | name_template: >- | 34 | name_template: >- | ||
| 37 | {{ .ProjectName }}_{{ .Os }}_{{ if eq .Arch "amd64" }}x86_64{{ else }}{{ .Arch }}{{ end }} | 35 | {{ .ProjectName }}_{{ .Os }}_{{ if eq .Arch "amd64" }}x86_64{{ else }}{{ .Arch }}{{ end }} | ||
| 38 | formats: ['tar.gz'] | 36 | formats: ['tar.gz'] | ||
| @@ -89,7 +87,7 @@ release: | |||||
| 89 | 87 | ||||
| 90 | ## Install | 88 | ## Install | ||
| 91 | 89 | ||||
| 92 | - | ### Script (Linux x86_64, macOS arm64) | 90 | + | ### Script (Linux x86_64/arm64, macOS arm64) |
| 93 | ```sh | 91 | ```sh | ||
| 94 | curl -fsSL https://raw.githubusercontent.com/bnema/vev/{{ .Tag }}/install.sh | VEV_VERSION={{ .Tag }} sh | 92 | curl -fsSL https://raw.githubusercontent.com/bnema/vev/{{ .Tag }}/install.sh | VEV_VERSION={{ .Tag }} sh | ||
| 95 | ``` | 93 | ``` | ||
M Makefile +4 -1
| @@ -1,4 +1,4 @@ | |||
| 1 | - | .PHONY: install test lint mocks | |
| 1 | + | .PHONY: install test test-installer lint mocks | |
| 2 | 2 | ||
| 3 | 3 | install: | |
| 4 | 4 | go install . | |
| @@ -10,6 +10,9 @@ install: | |||
| 10 | 10 | test: | |
| 11 | 11 | go test ./... -race | |
| 12 | 12 | ||
| 13 | + | test-installer: | |
| 14 | + | sh scripts/install_platform_test.sh | |
| 15 | + | ||
| 13 | 16 | lint: | |
| 14 | 17 | @test -z "$$(goimports -l .)" | |
| 15 | 18 | go vet ./... | |
| @@ -1,4 +1,4 @@ | |||||
| 1 | - | .PHONY: install test lint mocks | 1 | + | .PHONY: install test test-installer lint mocks |
| 2 | 2 | ||||
| 3 | install: | 3 | install: | ||
| 4 | go install . | 4 | go install . | ||
| @@ -10,6 +10,9 @@ install: | |||||
| 10 | test: | 10 | test: | ||
| 11 | go test ./... -race | 11 | go test ./... -race | ||
| 12 | 12 | ||||
| 13 | + | test-installer: | |||
| 14 | + | sh scripts/install_platform_test.sh | |||
| 15 | + | ||||
| 13 | lint: | 16 | lint: | ||
| 14 | @test -z "$$(goimports -l .)" | 17 | @test -z "$$(goimports -l .)" | ||
| 15 | go vet ./... | 18 | go vet ./... | ||
M README.md +10 -2
| @@ -7,7 +7,7 @@ A terminal multiplexer for Linux and macOS on Apple silicon (arm64). One Go bina | |||
| 7 | 7 | > [!WARNING] | |
| 8 | 8 | > Alpha software. Expect breaking changes. | |
| 9 | 9 | ||
| 10 | - | CI covers Ubuntu and macOS arm64. The release installer supports Linux x86_64 and macOS arm64. | |
| 10 | + | Pre-built releases are available for Linux x86_64, Linux arm64, and macOS on Apple silicon (arm64). CI tests on Ubuntu x86_64 and macOS arm64; it also verifies cross-compilation for Linux arm64 and macOS arm64. Linux arm64 is not tested on native ARM hardware. | |
| 11 | 11 | ||
| 12 | 12 | What it is built around: | |
| 13 | 13 | ||
| @@ -18,11 +18,19 @@ What it is built around: | |||
| 18 | 18 | ||
| 19 | 19 | ## Install | |
| 20 | 20 | ||
| 21 | + | Install a pre-built release on Linux x86_64/arm64 or macOS Apple silicon (arm64): | |
| 22 | + | ||
| 23 | + | ```sh | |
| 24 | + | curl -fsSL https://raw.githubusercontent.com/bnema/vev/main/install.sh | sh | |
| 25 | + | ``` | |
| 26 | + | ||
| 27 | + | Alternatively, build and install the binary with Go: | |
| 28 | + | ||
| 21 | 29 | ```sh | |
| 22 | 30 | go install github.com/bnema/vev@latest | |
| 23 | 31 | ``` | |
| 24 | 32 | ||
| 25 | - | The default UI runs entirely from the `vev` binary. Optional external bar anchors can be configured in `~/.config/vev/config`. | |
| 33 | + | The default UI runs entirely from the `vev` binary. The pre-built installer also installs optional external bar anchors, which only take effect when configured in `~/.config/vev/config`. | |
| 26 | 34 | ||
| 27 | 35 | ## Usage | |
| 28 | 36 | ||
| @@ -7,7 +7,7 @@ A terminal multiplexer for Linux and macOS on Apple silicon (arm64). One Go bina | |||||
| 7 | > [!WARNING] | 7 | > [!WARNING] | ||
| 8 | > Alpha software. Expect breaking changes. | 8 | > Alpha software. Expect breaking changes. | ||
| 9 | 9 | ||||
| 10 | - | CI covers Ubuntu and macOS arm64. The release installer supports Linux x86_64 and macOS arm64. | 10 | + | Pre-built releases are available for Linux x86_64, Linux arm64, and macOS on Apple silicon (arm64). CI tests on Ubuntu x86_64 and macOS arm64; it also verifies cross-compilation for Linux arm64 and macOS arm64. Linux arm64 is not tested on native ARM hardware. |
| 11 | 11 | ||||
| 12 | What it is built around: | 12 | What it is built around: | ||
| 13 | 13 | ||||
| @@ -18,11 +18,19 @@ What it is built around: | |||||
| 18 | 18 | ||||
| 19 | ## Install | 19 | ## Install | ||
| 20 | 20 | ||||
| 21 | + | Install a pre-built release on Linux x86_64/arm64 or macOS Apple silicon (arm64): | |||
| 22 | + | ||||
| 23 | + | ```sh | |||
| 24 | + | curl -fsSL https://raw.githubusercontent.com/bnema/vev/main/install.sh | sh | |||
| 25 | + | ``` | |||
| 26 | + | ||||
| 27 | + | Alternatively, build and install the binary with Go: | |||
| 28 | + | ||||
| 21 | ```sh | 29 | ```sh | ||
| 22 | go install github.com/bnema/vev@latest | 30 | go install github.com/bnema/vev@latest | ||
| 23 | ``` | 31 | ``` | ||
| 24 | 32 | ||||
| 25 | - | The default UI runs entirely from the `vev` binary. Optional external bar anchors can be configured in `~/.config/vev/config`. | 33 | + | The default UI runs entirely from the `vev` binary. The pre-built installer also installs optional external bar anchors, which only take effect when configured in `~/.config/vev/config`. |
| 26 | 34 | ||||
| 27 | ## Usage | 35 | ## Usage | ||
| 28 | 36 | ||||
M cmd/vev-perf-harness/launcher.go +17 -0
| @@ -628,6 +628,23 @@ func (e *ptyLocalEcho) applicationOutput(chunk []byte) []byte { | |||
| 628 | 628 | func (p *cliProcess) Close() error { | |
| 629 | 629 | var result error | |
| 630 | 630 | p.closed.Do(func() { | |
| 631 | + | // No measurement waits for terminal chunks during teardown. Continue | |
| 632 | + | // consuming them so a full channel cannot block the client before it | |
| 633 | + | // receives the shell exit request and closes its transport receive span. | |
| 634 | + | if p.chunks != nil && p.done != nil { | |
| 635 | + | go func() { | |
| 636 | + | for { | |
| 637 | + | select { | |
| 638 | + | case _, ok := <-p.chunks: | |
| 639 | + | if !ok { | |
| 640 | + | return | |
| 641 | + | } | |
| 642 | + | case <-p.done: | |
| 643 | + | return | |
| 644 | + | } | |
| 645 | + | } | |
| 646 | + | }() | |
| 647 | + | } | |
| 631 | 648 | // A public terminal client owns a shell session. Ask that shell to exit | |
| 632 | 649 | // before closing the PTY so its transport can finish its receive span; | |
| 633 | 650 | // this avoids turning ordinary harness teardown into an aborted trace. | |
| @@ -628,6 +628,23 @@ func (e *ptyLocalEcho) applicationOutput(chunk []byte) []byte { | |||||
| 628 | func (p *cliProcess) Close() error { | 628 | func (p *cliProcess) Close() error { | ||
| 629 | var result error | 629 | var result error | ||
| 630 | p.closed.Do(func() { | 630 | p.closed.Do(func() { | ||
| 631 | + | // No measurement waits for terminal chunks during teardown. Continue | |||
| 632 | + | // consuming them so a full channel cannot block the client before it | |||
| 633 | + | // receives the shell exit request and closes its transport receive span. | |||
| 634 | + | if p.chunks != nil && p.done != nil { | |||
| 635 | + | go func() { | |||
| 636 | + | for { | |||
| 637 | + | select { | |||
| 638 | + | case _, ok := <-p.chunks: | |||
| 639 | + | if !ok { | |||
| 640 | + | return | |||
| 641 | + | } | |||
| 642 | + | case <-p.done: | |||
| 643 | + | return | |||
| 644 | + | } | |||
| 645 | + | } | |||
| 646 | + | }() | |||
| 647 | + | } | |||
| 631 | // A public terminal client owns a shell session. Ask that shell to exit | 648 | // A public terminal client owns a shell session. Ask that shell to exit | ||
| 632 | // before closing the PTY so its transport can finish its receive span; | 649 | // before closing the PTY so its transport can finish its receive span; | ||
| 633 | // this avoids turning ordinary harness teardown into an aborted trace. | 650 | // this avoids turning ordinary harness teardown into an aborted trace. | ||
M cmd/vev-perf-harness/launcher_test.go +50 -0
| @@ -18,6 +18,56 @@ import ( | |||
| 18 | 18 | "github.com/bnema/vev/pkg/safedir" | |
| 19 | 19 | ) | |
| 20 | 20 | ||
| 21 | + | type discardTerminalOutput struct{} | |
| 22 | + | ||
| 23 | + | func (discardTerminalOutput) Write(p []byte) (int, error) { return len(p), nil } | |
| 24 | + | func (discardTerminalOutput) Sync() error { return nil } | |
| 25 | + | func (discardTerminalOutput) Close() error { return nil } | |
| 26 | + | ||
| 27 | + | func TestCLIProcessCloseDrainsQueuedTerminalOutputBeforeClientExit(t *testing.T) { | |
| 28 | + | harnessPTY, clientPTY := net.Pipe() | |
| 29 | + | t.Cleanup(func() { _ = clientPTY.Close() }) | |
| 30 | + | waitErr := make(chan error) | |
| 31 | + | secondRead := make(chan struct{}) | |
| 32 | + | p := &cliProcess{ | |
| 33 | + | pty: harnessPTY, | |
| 34 | + | output: discardTerminalOutput{}, | |
| 35 | + | chunks: make(chan []byte, 1), | |
| 36 | + | done: make(chan struct{}), | |
| 37 | + | waitErr: waitErr, | |
| 38 | + | waitTimeout: func() <-chan time.Time { return time.After(time.Second) }, | |
| 39 | + | } | |
| 40 | + | go p.copyTerminal() | |
| 41 | + | go func() { | |
| 42 | + | _, _ = clientPTY.Write([]byte("first")) | |
| 43 | + | _, _ = clientPTY.Write([]byte("second")) | |
| 44 | + | close(secondRead) | |
| 45 | + | buf := make([]byte, len("exit\n")) | |
| 46 | + | if _, err := clientPTY.Read(buf); err != nil { | |
| 47 | + | return | |
| 48 | + | } | |
| 49 | + | if _, err := clientPTY.Write([]byte("third")); err != nil { | |
| 50 | + | return | |
| 51 | + | } | |
| 52 | + | waitErr <- nil | |
| 53 | + | }() | |
| 54 | + | select { | |
| 55 | + | case <-secondRead: | |
| 56 | + | case <-time.After(time.Second): | |
| 57 | + | t.Fatal("terminal reader did not queue output") | |
| 58 | + | } | |
| 59 | + | closed := make(chan error, 1) | |
| 60 | + | go func() { closed <- p.Close() }() | |
| 61 | + | select { | |
| 62 | + | case err := <-closed: | |
| 63 | + | if err != nil { | |
| 64 | + | t.Fatal(err) | |
| 65 | + | } | |
| 66 | + | case <-time.After(time.Second): | |
| 67 | + | t.Fatal("Close did not drain queued terminal output before waiting for client exit") | |
| 68 | + | } | |
| 69 | + | } | |
| 70 | + | ||
| 21 | 71 | func TestCLIProcessCloseKeepsTerminalDrainActiveUntilClientExit(t *testing.T) { | |
| 22 | 72 | pty, err := os.CreateTemp(t.TempDir(), "pty") | |
| 23 | 73 | if err != nil { | |
| @@ -18,6 +18,56 @@ import ( | |||||
| 18 | "github.com/bnema/vev/pkg/safedir" | 18 | "github.com/bnema/vev/pkg/safedir" | ||
| 19 | ) | 19 | ) | ||
| 20 | 20 | ||||
| 21 | + | type discardTerminalOutput struct{} | |||
| 22 | + | ||||
| 23 | + | func (discardTerminalOutput) Write(p []byte) (int, error) { return len(p), nil } | |||
| 24 | + | func (discardTerminalOutput) Sync() error { return nil } | |||
| 25 | + | func (discardTerminalOutput) Close() error { return nil } | |||
| 26 | + | ||||
| 27 | + | func TestCLIProcessCloseDrainsQueuedTerminalOutputBeforeClientExit(t *testing.T) { | |||
| 28 | + | harnessPTY, clientPTY := net.Pipe() | |||
| 29 | + | t.Cleanup(func() { _ = clientPTY.Close() }) | |||
| 30 | + | waitErr := make(chan error) | |||
| 31 | + | secondRead := make(chan struct{}) | |||
| 32 | + | p := &cliProcess{ | |||
| 33 | + | pty: harnessPTY, | |||
| 34 | + | output: discardTerminalOutput{}, | |||
| 35 | + | chunks: make(chan []byte, 1), | |||
| 36 | + | done: make(chan struct{}), | |||
| 37 | + | waitErr: waitErr, | |||
| 38 | + | waitTimeout: func() <-chan time.Time { return time.After(time.Second) }, | |||
| 39 | + | } | |||
| 40 | + | go p.copyTerminal() | |||
| 41 | + | go func() { | |||
| 42 | + | _, _ = clientPTY.Write([]byte("first")) | |||
| 43 | + | _, _ = clientPTY.Write([]byte("second")) | |||
| 44 | + | close(secondRead) | |||
| 45 | + | buf := make([]byte, len("exit\n")) | |||
| 46 | + | if _, err := clientPTY.Read(buf); err != nil { | |||
| 47 | + | return | |||
| 48 | + | } | |||
| 49 | + | if _, err := clientPTY.Write([]byte("third")); err != nil { | |||
| 50 | + | return | |||
| 51 | + | } | |||
| 52 | + | waitErr <- nil | |||
| 53 | + | }() | |||
| 54 | + | select { | |||
| 55 | + | case <-secondRead: | |||
| 56 | + | case <-time.After(time.Second): | |||
| 57 | + | t.Fatal("terminal reader did not queue output") | |||
| 58 | + | } | |||
| 59 | + | closed := make(chan error, 1) | |||
| 60 | + | go func() { closed <- p.Close() }() | |||
| 61 | + | select { | |||
| 62 | + | case err := <-closed: | |||
| 63 | + | if err != nil { | |||
| 64 | + | t.Fatal(err) | |||
| 65 | + | } | |||
| 66 | + | case <-time.After(time.Second): | |||
| 67 | + | t.Fatal("Close did not drain queued terminal output before waiting for client exit") | |||
| 68 | + | } | |||
| 69 | + | } | |||
| 70 | + | ||||
| 21 | func TestCLIProcessCloseKeepsTerminalDrainActiveUntilClientExit(t *testing.T) { | 71 | func TestCLIProcessCloseKeepsTerminalDrainActiveUntilClientExit(t *testing.T) { | ||
| 22 | pty, err := os.CreateTemp(t.TempDir(), "pty") | 72 | pty, err := os.CreateTemp(t.TempDir(), "pty") | ||
| 23 | if err != nil { | 73 | if err != nil { | ||
M install.sh +5 -4
| @@ -1,5 +1,5 @@ | |||
| 1 | 1 | #!/bin/sh | |
| 2 | - | # vev installer — Linux x86_64 and macOS arm64. | |
| 2 | + | # vev installer — Linux x86_64/arm64 and macOS arm64. | |
| 3 | 3 | # Usage: curl -fsSL https://raw.githubusercontent.com/bnema/vev/main/install.sh | sh | |
| 4 | 4 | # Env: VEV_VERSION=vX.Y.Z to pin a version (default: latest release). | |
| 5 | 5 | set -eu | |
| @@ -14,9 +14,10 @@ err() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; } | |||
| 14 | 14 | OS="$(uname -s | tr '[:upper:]' '[:lower:]')" | |
| 15 | 15 | ARCH="$(uname -m)" | |
| 16 | 16 | case "$OS/$ARCH" in | |
| 17 | - | linux/x86_64|linux/amd64) TARBALL="vev_linux_x86_64.tar.gz" ;; | |
| 18 | - | darwin/arm64) TARBALL="vev_darwin_arm64.tar.gz" ;; | |
| 19 | - | *) err "unsupported platform: $OS/$ARCH (supported: linux/x86_64, darwin/arm64)" ;; | |
| 17 | + | linux/x86_64|linux/amd64) TARBALL="vev_linux_x86_64.tar.gz" ;; | |
| 18 | + | linux/aarch64|linux/arm64) TARBALL="vev_linux_arm64.tar.gz" ;; | |
| 19 | + | darwin/arm64) TARBALL="vev_darwin_arm64.tar.gz" ;; | |
| 20 | + | *) err "unsupported platform: $OS/$ARCH (supported: linux/x86_64, linux/arm64, darwin/arm64)" ;; | |
| 20 | 21 | esac | |
| 21 | 22 | ||
| 22 | 23 | # --- Pick install dir ------------------------------------------------------ | |
| @@ -1,5 +1,5 @@ | |||||
| 1 | #!/bin/sh | 1 | #!/bin/sh | ||
| 2 | - | # vev installer — Linux x86_64 and macOS arm64. | 2 | + | # vev installer — Linux x86_64/arm64 and macOS arm64. |
| 3 | # Usage: curl -fsSL https://raw.githubusercontent.com/bnema/vev/main/install.sh | sh | 3 | # Usage: curl -fsSL https://raw.githubusercontent.com/bnema/vev/main/install.sh | sh | ||
| 4 | # Env: VEV_VERSION=vX.Y.Z to pin a version (default: latest release). | 4 | # Env: VEV_VERSION=vX.Y.Z to pin a version (default: latest release). | ||
| 5 | set -eu | 5 | set -eu | ||
| @@ -14,9 +14,10 @@ err() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; } | |||||
| 14 | OS="$(uname -s | tr '[:upper:]' '[:lower:]')" | 14 | OS="$(uname -s | tr '[:upper:]' '[:lower:]')" | ||
| 15 | ARCH="$(uname -m)" | 15 | ARCH="$(uname -m)" | ||
| 16 | case "$OS/$ARCH" in | 16 | case "$OS/$ARCH" in | ||
| 17 | - | linux/x86_64|linux/amd64) TARBALL="vev_linux_x86_64.tar.gz" ;; | 17 | + | linux/x86_64|linux/amd64) TARBALL="vev_linux_x86_64.tar.gz" ;; |
| 18 | - | darwin/arm64) TARBALL="vev_darwin_arm64.tar.gz" ;; | 18 | + | linux/aarch64|linux/arm64) TARBALL="vev_linux_arm64.tar.gz" ;; |
| 19 | - | *) err "unsupported platform: $OS/$ARCH (supported: linux/x86_64, darwin/arm64)" ;; | 19 | + | darwin/arm64) TARBALL="vev_darwin_arm64.tar.gz" ;; |
| 20 | + | *) err "unsupported platform: $OS/$ARCH (supported: linux/x86_64, linux/arm64, darwin/arm64)" ;; | |||
| 20 | esac | 21 | esac | ||
| 21 | 22 | ||||
| 22 | # --- Pick install dir ------------------------------------------------------ | 23 | # --- Pick install dir ------------------------------------------------------ | ||
A scripts/install_platform_test.sh +73 -0
| @@ -0,0 +1,73 @@ | |||
| 1 | + | #!/bin/sh | |
| 2 | + | set -eu | |
| 3 | + | ||
| 4 | + | ROOT_DIR=$(CDPATH='' cd "$(dirname "$0")/.." && pwd) | |
| 5 | + | TEST_DIR=$(mktemp -d) | |
| 6 | + | trap 'rm -rf "$TEST_DIR"' EXIT HUP INT TERM | |
| 7 | + | ||
| 8 | + | FAKE_BIN="$TEST_DIR/bin" | |
| 9 | + | mkdir -p "$FAKE_BIN" | |
| 10 | + | ||
| 11 | + | cat >"$FAKE_BIN/uname" <<'EOF' | |
| 12 | + | #!/bin/sh | |
| 13 | + | case "${1:-}" in | |
| 14 | + | -s) printf '%s\n' "$FAKE_OS" ;; | |
| 15 | + | -m) printf '%s\n' "$FAKE_ARCH" ;; | |
| 16 | + | *) exit 2 ;; | |
| 17 | + | esac | |
| 18 | + | EOF | |
| 19 | + | ||
| 20 | + | cat >"$FAKE_BIN/curl" <<'EOF' | |
| 21 | + | #!/bin/sh | |
| 22 | + | printf '%s\n' "$*" >>"$CURL_LOG" | |
| 23 | + | exit 97 | |
| 24 | + | EOF | |
| 25 | + | ||
| 26 | + | chmod +x "$FAKE_BIN/uname" "$FAKE_BIN/curl" | |
| 27 | + | ||
| 28 | + | fail() { | |
| 29 | + | printf 'FAIL: %s\n' "$*" >&2 | |
| 30 | + | exit 1 | |
| 31 | + | } | |
| 32 | + | ||
| 33 | + | assert_mapping() { | |
| 34 | + | os=$1 | |
| 35 | + | arch=$2 | |
| 36 | + | tarball=$3 | |
| 37 | + | curl_log="$TEST_DIR/curl-$os-$arch.log" | |
| 38 | + | output="$TEST_DIR/output-$os-$arch.log" | |
| 39 | + | ||
| 40 | + | if FAKE_OS=$os FAKE_ARCH=$arch CURL_LOG=$curl_log HOME="$TEST_DIR/home" \ | |
| 41 | + | PATH="$FAKE_BIN:$PATH" VEV_VERSION=v0.0.0 \ | |
| 42 | + | sh "$ROOT_DIR/install.sh" >"$output" 2>&1; then | |
| 43 | + | fail "$os/$arch unexpectedly completed installation" | |
| 44 | + | fi | |
| 45 | + | ||
| 46 | + | expected_url="https://github.com/bnema/vev/releases/download/v0.0.0/$tarball" | |
| 47 | + | [ -f "$curl_log" ] || fail "$os/$arch did not attempt a download" | |
| 48 | + | grep -F "$expected_url" "$curl_log" >/dev/null \ | |
| 49 | + | || fail "$os/$arch did not select $tarball" | |
| 50 | + | [ "$(wc -l <"$curl_log" | tr -d ' ')" = 1 ] \ | |
| 51 | + | || fail "$os/$arch attempted more than the archive download" | |
| 52 | + | } | |
| 53 | + | ||
| 54 | + | assert_mapping Linux x86_64 vev_linux_x86_64.tar.gz | |
| 55 | + | assert_mapping Linux amd64 vev_linux_x86_64.tar.gz | |
| 56 | + | assert_mapping Linux aarch64 vev_linux_arm64.tar.gz | |
| 57 | + | assert_mapping Linux arm64 vev_linux_arm64.tar.gz | |
| 58 | + | assert_mapping Darwin arm64 vev_darwin_arm64.tar.gz | |
| 59 | + | ||
| 60 | + | curl_log="$TEST_DIR/curl-Linux-armv7l.log" | |
| 61 | + | output="$TEST_DIR/output-Linux-armv7l.log" | |
| 62 | + | if FAKE_OS=Linux FAKE_ARCH=armv7l CURL_LOG=$curl_log HOME="$TEST_DIR/home" \ | |
| 63 | + | PATH="$FAKE_BIN:$PATH" VEV_VERSION=v0.0.0 \ | |
| 64 | + | sh "$ROOT_DIR/install.sh" >"$output" 2>&1; then | |
| 65 | + | fail "Linux/armv7l unexpectedly succeeded" | |
| 66 | + | fi | |
| 67 | + | grep -F "unsupported platform: linux/armv7l" "$output" >/dev/null \ | |
| 68 | + | || fail "Linux/armv7l did not report an unsupported platform" | |
| 69 | + | grep -F "supported: linux/x86_64, linux/arm64, darwin/arm64" "$output" >/dev/null \ | |
| 70 | + | || fail "Linux/armv7l did not list the canonical supported platforms" | |
| 71 | + | [ ! -e "$curl_log" ] || fail "Linux/armv7l invoked curl before rejection" | |
| 72 | + | ||
| 73 | + | printf 'installer platform tests passed\n' | |
| @@ -0,0 +1,73 @@ | |||||
| 1 | + | #!/bin/sh | |||
| 2 | + | set -eu | |||
| 3 | + | ||||
| 4 | + | ROOT_DIR=$(CDPATH='' cd "$(dirname "$0")/.." && pwd) | |||
| 5 | + | TEST_DIR=$(mktemp -d) | |||
| 6 | + | trap 'rm -rf "$TEST_DIR"' EXIT HUP INT TERM | |||
| 7 | + | ||||
| 8 | + | FAKE_BIN="$TEST_DIR/bin" | |||
| 9 | + | mkdir -p "$FAKE_BIN" | |||
| 10 | + | ||||
| 11 | + | cat >"$FAKE_BIN/uname" <<'EOF' | |||
| 12 | + | #!/bin/sh | |||
| 13 | + | case "${1:-}" in | |||
| 14 | + | -s) printf '%s\n' "$FAKE_OS" ;; | |||
| 15 | + | -m) printf '%s\n' "$FAKE_ARCH" ;; | |||
| 16 | + | *) exit 2 ;; | |||
| 17 | + | esac | |||
| 18 | + | EOF | |||
| 19 | + | ||||
| 20 | + | cat >"$FAKE_BIN/curl" <<'EOF' | |||
| 21 | + | #!/bin/sh | |||
| 22 | + | printf '%s\n' "$*" >>"$CURL_LOG" | |||
| 23 | + | exit 97 | |||
| 24 | + | EOF | |||
| 25 | + | ||||
| 26 | + | chmod +x "$FAKE_BIN/uname" "$FAKE_BIN/curl" | |||
| 27 | + | ||||
| 28 | + | fail() { | |||
| 29 | + | printf 'FAIL: %s\n' "$*" >&2 | |||
| 30 | + | exit 1 | |||
| 31 | + | } | |||
| 32 | + | ||||
| 33 | + | assert_mapping() { | |||
| 34 | + | os=$1 | |||
| 35 | + | arch=$2 | |||
| 36 | + | tarball=$3 | |||
| 37 | + | curl_log="$TEST_DIR/curl-$os-$arch.log" | |||
| 38 | + | output="$TEST_DIR/output-$os-$arch.log" | |||
| 39 | + | ||||
| 40 | + | if FAKE_OS=$os FAKE_ARCH=$arch CURL_LOG=$curl_log HOME="$TEST_DIR/home" \ | |||
| 41 | + | PATH="$FAKE_BIN:$PATH" VEV_VERSION=v0.0.0 \ | |||
| 42 | + | sh "$ROOT_DIR/install.sh" >"$output" 2>&1; then | |||
| 43 | + | fail "$os/$arch unexpectedly completed installation" | |||
| 44 | + | fi | |||
| 45 | + | ||||
| 46 | + | expected_url="https://github.com/bnema/vev/releases/download/v0.0.0/$tarball" | |||
| 47 | + | [ -f "$curl_log" ] || fail "$os/$arch did not attempt a download" | |||
| 48 | + | grep -F "$expected_url" "$curl_log" >/dev/null \ | |||
| 49 | + | || fail "$os/$arch did not select $tarball" | |||
| 50 | + | [ "$(wc -l <"$curl_log" | tr -d ' ')" = 1 ] \ | |||
| 51 | + | || fail "$os/$arch attempted more than the archive download" | |||
| 52 | + | } | |||
| 53 | + | ||||
| 54 | + | assert_mapping Linux x86_64 vev_linux_x86_64.tar.gz | |||
| 55 | + | assert_mapping Linux amd64 vev_linux_x86_64.tar.gz | |||
| 56 | + | assert_mapping Linux aarch64 vev_linux_arm64.tar.gz | |||
| 57 | + | assert_mapping Linux arm64 vev_linux_arm64.tar.gz | |||
| 58 | + | assert_mapping Darwin arm64 vev_darwin_arm64.tar.gz | |||
| 59 | + | ||||
| 60 | + | curl_log="$TEST_DIR/curl-Linux-armv7l.log" | |||
| 61 | + | output="$TEST_DIR/output-Linux-armv7l.log" | |||
| 62 | + | if FAKE_OS=Linux FAKE_ARCH=armv7l CURL_LOG=$curl_log HOME="$TEST_DIR/home" \ | |||
| 63 | + | PATH="$FAKE_BIN:$PATH" VEV_VERSION=v0.0.0 \ | |||
| 64 | + | sh "$ROOT_DIR/install.sh" >"$output" 2>&1; then | |||
| 65 | + | fail "Linux/armv7l unexpectedly succeeded" | |||
| 66 | + | fi | |||
| 67 | + | grep -F "unsupported platform: linux/armv7l" "$output" >/dev/null \ | |||
| 68 | + | || fail "Linux/armv7l did not report an unsupported platform" | |||
| 69 | + | grep -F "supported: linux/x86_64, linux/arm64, darwin/arm64" "$output" >/dev/null \ | |||
| 70 | + | || fail "Linux/armv7l did not list the canonical supported platforms" | |||
| 71 | + | [ ! -e "$curl_log" ] || fail "Linux/armv7l invoked curl before rejection" | |||
| 72 | + | ||||
| 73 | + | printf 'installer platform tests passed\n' | |||