Close piped processes on cancellation

This commit is contained in:
2026-11-02 03:16:36 +00:00
parent 9c02ed769b
commit 595745c7b1
6 changed files with 150 additions and 1 deletions

View File

@@ -6,12 +6,58 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"testing"
"time"
releasekit "go.maximumdirect.net/releasekit"
)
func TestPrepareBuildDependenciesCancellationReleasesInheritedOutput(t *testing.T) {
directory := t.TempDir()
ready := filepath.Join(t.TempDir(), "descendant")
gitPath := filepath.Join(t.TempDir(), "git")
if err := os.WriteFile(gitPath, []byte("#!/bin/sh\nsleep 60 &\nprintf '%s' \"$!\" > \"$RELEASEKIT_PREPARE_DESCENDANT\"\nwait\n"), 0o700); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", filepath.Dir(gitPath)+string(os.PathListSeparator)+os.Getenv("PATH"))
t.Setenv("RELEASEKIT_PREPARE_DESCENDANT", ready)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
result := make(chan error, 1)
go func() {
result <- releasekit.PrepareBuildDependencies(ctx, releasekit.DependencyPreparationRequest{RepositoryDir: directory})
}()
deadline := time.After(10 * time.Second)
var pid int
for pid == 0 {
if data, err := os.ReadFile(ready); err == nil {
pid, _ = strconv.Atoi(string(data))
}
select {
case <-deadline:
t.Fatal("preparation descendant did not start")
default:
time.Sleep(10 * time.Millisecond)
}
}
t.Cleanup(func() {
if descendant, err := os.FindProcess(pid); err == nil {
_ = descendant.Kill()
}
})
cancel()
select {
case err := <-result:
if !errors.Is(err, context.Canceled) {
t.Fatalf("preparation error = %v, want cancellation", err)
}
case <-time.After(10 * time.Second):
t.Fatal("preparation did not return after cancellation")
}
}
func TestPrepareTaggedCheckoutFetchesExpectedCommitAndDetaches(t *testing.T) {
repository := newTaggedDeliveryConsumer(t)
tagCommit := publishPreparationTag(t, repository)