From 7b271823c813c796462e7bbe45e800b995d34613 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Sun, 6 Sep 2026 08:33:34 +0000 Subject: [PATCH 1/2] chore(ci): update Go to 1.27.1 --- .github/workflows/ci.yml | 8 ++++---- go.mod | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2c57c2..479982f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: ["1.26", "1.26.5"] + go-version: ["1.27", "1.27.1"] steps: - uses: actions/checkout@v7 @@ -39,7 +39,7 @@ jobs: run: sudo env GOTOOLCHAIN=local "$(go env GOROOT)/bin/go" test -race -coverprofile=coverage-root.out -covermode=atomic ./... - name: Upload coverage to Codecov - if: matrix.go-version == '1.26.5' + if: matrix.go-version == '1.27.1' uses: codecov/codecov-action@v7 with: files: coverage-user.out,coverage-root.out @@ -55,7 +55,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27.1" cache: true - name: Check gofmt @@ -93,7 +93,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27.1" cache: true - name: Run govulncheck diff --git a/go.mod b/go.mod index e0b0c73..e8c3c2c 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/taigrr/systemctl -go 1.26.5 +go 1.27.1 From a8d5bae4b4b1bfa354d192fbda5f91cd08c5d1e4 Mon Sep 17 00:00:00 2001 From: Tai Groot Date: Tue, 29 Sep 2026 07:33:29 +0000 Subject: [PATCH 2/2] fix(systemctl): handle missing binary execution --- util.go | 6 +++++- util_test.go | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/util.go b/util.go index e01a906..4ff98f8 100644 --- a/util.go +++ b/util.go @@ -38,7 +38,11 @@ func execute(ctx context.Context, args []string) (string, string, int, error) { err = cmd.Run() output = stdout.String() warnings = stderr.String() - code = cmd.ProcessState.ExitCode() + if cmd.ProcessState != nil { + code = cmd.ProcessState.ExitCode() + } else { + code = 1 + } if code == killed { return output, warnings, code, ErrExecTimeout diff --git a/util_test.go b/util_test.go index 278166c..952314f 100644 --- a/util_test.go +++ b/util_test.go @@ -1,6 +1,9 @@ package systemctl import ( + "context" + "errors" + "os" "reflect" "testing" ) @@ -61,6 +64,25 @@ func TestPrepareArgs(t *testing.T) { } } +func TestExecuteHandlesMissingBinaryAfterLookup(t *testing.T) { + originalSystemctl := systemctl + systemctl = "/path/to/missing/systemctl" + t.Cleanup(func() { + systemctl = originalSystemctl + }) + + _, _, code, err := execute(context.Background(), []string{"status", "missing.service"}) + if err == nil { + t.Fatal("execute() error = nil, want missing binary error") + } + if !errors.Is(err, os.ErrNotExist) { + t.Fatalf("execute() error = %v, want error wrapping %v", err, os.ErrNotExist) + } + if code == 0 { + t.Fatal("execute() code = 0, want non-zero code") + } +} + func TestParseMaskedUnits(t *testing.T) { stdout := `UNIT FILE STATE PRESET foo.service masked enabled