From 4b57a2bd7d291d8c67fd108af8e114219439c19d Mon Sep 17 00:00:00 2001 From: Virgil Date: Mon, 30 Mar 2026 05:46:27 +0000 Subject: [PATCH] chore(ax): propagate caller context through release workflows --- cmd/build/cmd_build.go | 6 +++--- cmd/build/cmd_pwa.go | 39 ++++++++++++++++++++++------------ cmd/build/cmd_sdk.go | 4 +--- cmd/ci/ci.go | 29 ++++++++++++++----------- pkg/api/provider.go | 6 +++--- pkg/release/changelog.go | 40 +++++++++++++++++++++++++++++------ pkg/release/changelog_test.go | 13 ++++++++++++ pkg/release/release.go | 14 ++++++++---- pkg/release/sdk.go | 11 ++++++---- pkg/release/version.go | 33 +++++++++++++++++++++++++---- pkg/release/version_test.go | 14 ++++++++++++ 11 files changed, 156 insertions(+), 53 deletions(-) diff --git a/cmd/build/cmd_build.go b/cmd/build/cmd_build.go index 2249b1e..100f7f3 100644 --- a/cmd/build/cmd_build.go +++ b/cmd/build/cmd_build.go @@ -71,7 +71,7 @@ var fromPathCmd = &cli.Command{ if fromPath == "" { return errPathRequired } - return runBuild(fromPath) + return runBuild(cmd.Context(), fromPath) }, } @@ -81,14 +81,14 @@ var pwaCmd = &cli.Command{ if pwaURL == "" { return errURLRequired } - return runPwaBuild(pwaURL) + return runPwaBuild(cmd.Context(), pwaURL) }, } var sdkBuildCmd = &cli.Command{ Use: "sdk", RunE: func(cmd *cli.Command, args []string) error { - return runBuildSDK(sdkSpec, sdkLang, sdkVersion, sdkDryRun) + return runBuildSDK(cmd.Context(), sdkSpec, sdkLang, sdkVersion, sdkDryRun) }, } diff --git a/cmd/build/cmd_pwa.go b/cmd/build/cmd_pwa.go index 1c19f85..1c3cd8c 100644 --- a/cmd/build/cmd_pwa.go +++ b/cmd/build/cmd_pwa.go @@ -28,7 +28,7 @@ var ( ) // runPwaBuild downloads a PWA from URL and builds it. -func runPwaBuild(pwaURL string) error { +func runPwaBuild(ctx context.Context, pwaURL string) error { core.Print(nil, "%s %s", i18n.T("cmd.build.pwa.starting"), pwaURL) tempDir, err := ax.TempDir("core-pwa-build-*") @@ -38,17 +38,17 @@ func runPwaBuild(pwaURL string) error { // defer os.RemoveAll(tempDir) // Keep temp dir for debugging core.Print(nil, "%s %s", i18n.T("cmd.build.pwa.downloading_to"), tempDir) - if err := downloadPWA(pwaURL, tempDir); err != nil { + if err := downloadPWA(ctx, pwaURL, tempDir); err != nil { return coreerr.E("pwa.runPwaBuild", i18n.T("common.error.failed", map[string]any{"Action": "download PWA"}), err) } - return runBuild(tempDir) + return runBuild(ctx, tempDir) } // downloadPWA fetches a PWA from a URL and saves assets locally. -func downloadPWA(baseURL, destDir string) error { +func downloadPWA(ctx context.Context, baseURL, destDir string) error { // Fetch the main HTML page - resp, err := http.Get(baseURL) + resp, err := getWithContext(ctx, baseURL) if err != nil { return coreerr.E("pwa.downloadPWA", i18n.T("common.error.failed", map[string]any{"Action": "fetch URL"})+" "+baseURL, err) } @@ -73,7 +73,7 @@ func downloadPWA(baseURL, destDir string) error { core.Print(nil, "%s %s", i18n.T("cmd.build.pwa.found_manifest"), manifestURL) // Fetch and parse the manifest - manifest, err := fetchManifest(manifestURL) + manifest, err := fetchManifest(ctx, manifestURL) if err != nil { return coreerr.E("pwa.downloadPWA", i18n.T("common.error.failed", map[string]any{"Action": "fetch or parse manifest"}), err) } @@ -81,7 +81,10 @@ func downloadPWA(baseURL, destDir string) error { // Download all assets listed in the manifest assets := collectAssets(manifest, manifestURL) for _, assetURL := range assets { - if err := downloadAsset(assetURL, destDir); err != nil { + if err := downloadAsset(ctx, assetURL, destDir); err != nil { + if ctx.Err() != nil { + return coreerr.E("pwa.downloadPWA", "download cancelled", ctx.Err()) + } core.Print(nil, "%s %s %s: %v", i18n.T("common.label.warning"), i18n.T("common.error.failed", map[string]any{"Action": "download asset"}), assetURL, err) } } @@ -144,8 +147,8 @@ func findManifestURL(htmlContent, baseURL string) (string, error) { } // fetchManifest downloads and parses a PWA manifest. -func fetchManifest(manifestURL string) (map[string]any, error) { - resp, err := http.Get(manifestURL) +func fetchManifest(ctx context.Context, manifestURL string) (map[string]any, error) { + resp, err := getWithContext(ctx, manifestURL) if err != nil { return nil, err } @@ -192,8 +195,8 @@ func collectAssets(manifest map[string]any, manifestURL string) []string { } // downloadAsset fetches a single asset and saves it locally. -func downloadAsset(assetURL, destDir string) error { - resp, err := http.Get(assetURL) +func downloadAsset(ctx context.Context, assetURL, destDir string) error { + resp, err := getWithContext(ctx, assetURL) if err != nil { return err } @@ -221,7 +224,7 @@ func downloadAsset(assetURL, destDir string) error { } // runBuild builds a desktop application from a local directory. -func runBuild(fromPath string) error { +func runBuild(ctx context.Context, fromPath string) error { core.Print(nil, "%s %s", i18n.T("cmd.build.from_path.starting"), fromPath) if !ax.IsDir(fromPath) { @@ -266,12 +269,12 @@ func runBuild(fromPath string) error { core.Println(i18n.T("cmd.build.from_path.compiling")) // Run go mod tidy - if err := ax.ExecDir(context.Background(), buildDir, "go", "mod", "tidy"); err != nil { + if err := ax.ExecDir(ctx, buildDir, "go", "mod", "tidy"); err != nil { return coreerr.E("pwa.runBuild", i18n.T("cmd.build.from_path.error.go_mod_tidy"), err) } // Run go build - if err := ax.ExecDir(context.Background(), buildDir, "go", "build", "-o", outputExe); err != nil { + if err := ax.ExecDir(ctx, buildDir, "go", "build", "-o", outputExe); err != nil { return coreerr.E("pwa.runBuild", i18n.T("cmd.build.from_path.error.go_build"), err) } @@ -280,6 +283,14 @@ func runBuild(fromPath string) error { return nil } +func getWithContext(ctx context.Context, targetURL string) (*http.Response, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, targetURL, nil) + if err != nil { + return nil, err + } + return http.DefaultClient.Do(req) +} + // copyDir recursively copies a directory from src to dst. func copyDir(src, dst string) error { if err := ax.MkdirAll(dst, 0o755); err != nil { diff --git a/cmd/build/cmd_sdk.go b/cmd/build/cmd_sdk.go index cb9dda9..d158583 100644 --- a/cmd/build/cmd_sdk.go +++ b/cmd/build/cmd_sdk.go @@ -17,9 +17,7 @@ import ( ) // runBuildSDK handles the `core build sdk` command. -func runBuildSDK(specPath, lang, version string, dryRun bool) error { - ctx := context.Background() - +func runBuildSDK(ctx context.Context, specPath, lang, version string, dryRun bool) error { projectDir, err := ax.Getwd() if err != nil { return coreerr.E("build.SDK", "failed to get working directory", err) diff --git a/cmd/ci/ci.go b/cmd/ci/ci.go index 77ecc23..48df74f 100644 --- a/cmd/ci/ci.go +++ b/cmd/ci/ci.go @@ -38,7 +38,7 @@ var ciCmd = &cli.Command{ Use: "ci", RunE: func(cmd *cli.Command, args []string) error { dryRun := !ciGoForLaunch - return runCIPublish(dryRun, ciVersion, ciDraft, ciPrerelease) + return runCIPublish(cmd.Context(), dryRun, ciVersion, ciDraft, ciPrerelease) }, } @@ -52,14 +52,14 @@ var ciInitCmd = &cli.Command{ var ciChangelogCmd = &cli.Command{ Use: "changelog", RunE: func(cmd *cli.Command, args []string) error { - return runChangelog(changelogFromRef, changelogToRef) + return runChangelog(cmd.Context(), changelogFromRef, changelogToRef) }, } var ciVersionCmd = &cli.Command{ Use: "version", RunE: func(cmd *cli.Command, args []string) error { - return runCIReleaseVersion() + return runCIReleaseVersion(cmd.Context()) }, } @@ -92,9 +92,7 @@ func initCIFlags() { } // runCIPublish publishes pre-built artifacts from dist/. -func runCIPublish(dryRun bool, version string, draft, prerelease bool) error { - ctx := context.Background() - +func runCIPublish(ctx context.Context, dryRun bool, version string, draft, prerelease bool) error { projectDir, err := ax.Getwd() if err != nil { return cli.WrapVerb(err, "get", "working directory") @@ -182,14 +180,14 @@ func runCIReleaseInit() error { } // runChangelog generates a changelog between two git refs. -func runChangelog(fromRef, toRef string) error { +func runChangelog(ctx context.Context, fromRef, toRef string) error { cwd, err := ax.Getwd() if err != nil { return cli.Err("%s: %w", i18n.T("i18n.fail.get", "working directory"), err) } if fromRef == "" || toRef == "" { - tag, err := latestTag(cwd) + tag, err := latestTagWithContext(ctx, cwd) if err == nil { if fromRef == "" { fromRef = tag @@ -198,6 +196,9 @@ func runChangelog(fromRef, toRef string) error { toRef = "HEAD" } } else { + if ctx.Err() != nil { + return ctx.Err() + } cli.Text(i18n.T("cmd.ci.changelog.no_tags")) return nil } @@ -205,7 +206,7 @@ func runChangelog(fromRef, toRef string) error { cli.Print("%s %s..%s\n\n", dimStyle.Render(i18n.T("cmd.ci.changelog.generating")), fromRef, toRef) - changelog, err := release.Generate(cwd, fromRef, toRef) + changelog, err := release.GenerateWithContext(ctx, cwd, fromRef, toRef) if err != nil { return cli.Err("%s: %w", i18n.T("i18n.fail.generate", "changelog"), err) } @@ -215,13 +216,13 @@ func runChangelog(fromRef, toRef string) error { } // runCIReleaseVersion shows the determined version. -func runCIReleaseVersion() error { +func runCIReleaseVersion(ctx context.Context) error { projectDir, err := ax.Getwd() if err != nil { return cli.WrapVerb(err, "get", "working directory") } - version, err := release.DetermineVersion(projectDir) + version, err := release.DetermineVersionWithContext(ctx, projectDir) if err != nil { return cli.WrapVerb(err, "determine", "version") } @@ -231,7 +232,11 @@ func runCIReleaseVersion() error { } func latestTag(dir string) (string, error) { - out, err := ax.RunDir(context.Background(), dir, "git", "describe", "--tags", "--abbrev=0") + return latestTagWithContext(context.Background(), dir) +} + +func latestTagWithContext(ctx context.Context, dir string) (string, error) { + out, err := ax.RunDir(ctx, dir, "git", "describe", "--tags", "--abbrev=0") if err != nil { return "", err } diff --git a/pkg/api/provider.go b/pkg/api/provider.go index 3a75428..251a822 100644 --- a/pkg/api/provider.go +++ b/pkg/api/provider.go @@ -275,7 +275,7 @@ func (p *BuildProvider) triggerBuild(c *gin.Context) { } // Determine version - version, verr := release.DetermineVersion(dir) + version, verr := release.DetermineVersionWithContext(c.Request.Context(), dir) if verr != nil { version = "dev" } @@ -406,7 +406,7 @@ func (p *BuildProvider) getVersion(c *gin.Context) { return } - version, err := release.DetermineVersion(dir) + version, err := release.DetermineVersionWithContext(c.Request.Context(), dir) if err != nil { c.JSON(http.StatusInternalServerError, api.Fail("version_failed", err.Error())) return @@ -428,7 +428,7 @@ func (p *BuildProvider) getChangelog(c *gin.Context) { fromRef := c.Query("from") toRef := c.Query("to") - changelog, err := release.Generate(dir, fromRef, toRef) + changelog, err := release.GenerateWithContext(c.Request.Context(), dir, fromRef, toRef) if err != nil { c.JSON(http.StatusInternalServerError, api.Fail("changelog_failed", err.Error())) return diff --git a/pkg/release/changelog.go b/pkg/release/changelog.go index 8059650..ae7e7d1 100644 --- a/pkg/release/changelog.go +++ b/pkg/release/changelog.go @@ -64,14 +64,25 @@ var conventionalCommitRegex = regexp.MustCompile(`^(\w+)(?:\(([^)]+)\))?(!)?:\s* // If toRef is empty, it uses HEAD. // Usage example: call release.Generate(...) from integrating code. func Generate(dir, fromRef, toRef string) (string, error) { + return GenerateWithContext(context.Background(), dir, fromRef, toRef) +} + +// GenerateWithContext generates a markdown changelog while honouring caller cancellation. +// If fromRef is empty, it uses the previous tag or initial commit. +// If toRef is empty, it uses HEAD. +// Usage example: call release.GenerateWithContext(...) from integrating code. +func GenerateWithContext(ctx context.Context, dir, fromRef, toRef string) (string, error) { if toRef == "" { toRef = "HEAD" } // If fromRef is empty, try to find previous tag if fromRef == "" { - prevTag, err := getPreviousTag(dir, toRef) + prevTag, err := getPreviousTagWithContext(ctx, dir, toRef) if err != nil { + if ctx.Err() != nil { + return "", coreerr.E("changelog.Generate", "generation cancelled", ctx.Err()) + } // No previous tag, use initial commit fromRef = "" } else { @@ -80,7 +91,7 @@ func Generate(dir, fromRef, toRef string) (string, error) { } // Get commits between refs - commits, err := getCommits(dir, fromRef, toRef) + commits, err := getCommitsWithContext(ctx, dir, fromRef, toRef) if err != nil { return "", coreerr.E("changelog.Generate", "failed to get commits", err) } @@ -101,14 +112,23 @@ func Generate(dir, fromRef, toRef string) (string, error) { // GenerateWithConfig generates a changelog with filtering based on config. // Usage example: call release.GenerateWithConfig(...) from integrating code. func GenerateWithConfig(dir, fromRef, toRef string, cfg *ChangelogConfig) (string, error) { + return GenerateWithConfigWithContext(context.Background(), dir, fromRef, toRef, cfg) +} + +// GenerateWithConfigWithContext generates a filtered changelog while honouring caller cancellation. +// Usage example: call release.GenerateWithConfigWithContext(...) from integrating code. +func GenerateWithConfigWithContext(ctx context.Context, dir, fromRef, toRef string, cfg *ChangelogConfig) (string, error) { if toRef == "" { toRef = "HEAD" } // If fromRef is empty, try to find previous tag if fromRef == "" { - prevTag, err := getPreviousTag(dir, toRef) + prevTag, err := getPreviousTagWithContext(ctx, dir, toRef) if err != nil { + if ctx.Err() != nil { + return "", coreerr.E("changelog.GenerateWithConfig", "generation cancelled", ctx.Err()) + } fromRef = "" } else { fromRef = prevTag @@ -116,7 +136,7 @@ func GenerateWithConfig(dir, fromRef, toRef string, cfg *ChangelogConfig) (strin } // Get commits between refs - commits, err := getCommits(dir, fromRef, toRef) + commits, err := getCommitsWithContext(ctx, dir, fromRef, toRef) if err != nil { return "", coreerr.E("changelog.GenerateWithConfig", "failed to get commits", err) } @@ -155,7 +175,11 @@ func GenerateWithConfig(dir, fromRef, toRef string, cfg *ChangelogConfig) (strin // getPreviousTag returns the tag before the given ref. func getPreviousTag(dir, ref string) (string, error) { - output, err := ax.RunDir(context.Background(), dir, "git", "describe", "--tags", "--abbrev=0", ref+"^") + return getPreviousTagWithContext(context.Background(), dir, ref) +} + +func getPreviousTagWithContext(ctx context.Context, dir, ref string) (string, error) { + output, err := ax.RunDir(ctx, dir, "git", "describe", "--tags", "--abbrev=0", ref+"^") if err != nil { return "", err } @@ -165,6 +189,10 @@ func getPreviousTag(dir, ref string) (string, error) { // getCommits returns a slice of commit strings between two refs. // Format: "hash subject" func getCommits(dir, fromRef, toRef string) ([]string, error) { + return getCommitsWithContext(context.Background(), dir, fromRef, toRef) +} + +func getCommitsWithContext(ctx context.Context, dir, fromRef, toRef string) ([]string, error) { var args []string if fromRef == "" { // All commits up to toRef @@ -174,7 +202,7 @@ func getCommits(dir, fromRef, toRef string) ([]string, error) { args = []string{"log", "--oneline", "--no-merges", fromRef + ".." + toRef} } - output, err := ax.RunDir(context.Background(), dir, "git", args...) + output, err := ax.RunDir(ctx, dir, "git", args...) if err != nil { return nil, err } diff --git a/pkg/release/changelog_test.go b/pkg/release/changelog_test.go index 60f7b88..1fc06b5 100644 --- a/pkg/release/changelog_test.go +++ b/pkg/release/changelog_test.go @@ -1,6 +1,7 @@ package release import ( + "context" "testing" "dappco.re/go/core/build/internal/ax" @@ -378,6 +379,18 @@ func TestChangelog_Generate_Bad(t *testing.T) { _, err := Generate(dir, "", "HEAD") assert.Error(t, err) }) + + t.Run("returns error when context is cancelled", func(t *testing.T) { + dir := setupChangelogGitRepo(t) + createChangelogCommit(t, dir, "feat: add new feature") + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + _, err := GenerateWithContext(ctx, dir, "", "HEAD") + require.Error(t, err) + assert.ErrorIs(t, err, context.Canceled) + }) } func TestChangelog_GenerateWithConfig_Good(t *testing.T) { diff --git a/pkg/release/release.go b/pkg/release/release.go index 4a57b62..980da51 100644 --- a/pkg/release/release.go +++ b/pkg/release/release.go @@ -55,7 +55,7 @@ func Publish(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) { // Step 1: Determine version version := cfg.version if version == "" { - version, err = DetermineVersion(absProjectDir) + version, err = DetermineVersionWithContext(ctx, absProjectDir) if err != nil { return nil, coreerr.E("release.Publish", "failed to determine version", err) } @@ -73,8 +73,11 @@ func Publish(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) { } // Step 3: Generate changelog - changelog, err := Generate(absProjectDir, "", version) + changelog, err := GenerateWithContext(ctx, absProjectDir, "", version) if err != nil { + if ctx.Err() != nil { + return nil, coreerr.E("release.Publish", "changelog generation cancelled", ctx.Err()) + } // Non-fatal: continue with empty changelog changelog = core.Sprintf("Release %s", version) } @@ -167,15 +170,18 @@ func Run(ctx context.Context, cfg *Config, dryRun bool) (*Release, error) { // Step 1: Determine version version := cfg.version if version == "" { - version, err = DetermineVersion(absProjectDir) + version, err = DetermineVersionWithContext(ctx, absProjectDir) if err != nil { return nil, coreerr.E("release.Run", "failed to determine version", err) } } // Step 2: Generate changelog - changelog, err := Generate(absProjectDir, "", version) + changelog, err := GenerateWithContext(ctx, absProjectDir, "", version) if err != nil { + if ctx.Err() != nil { + return nil, coreerr.E("release.Run", "changelog generation cancelled", ctx.Err()) + } // Non-fatal: continue with empty changelog changelog = core.Sprintf("Release %s", version) } diff --git a/pkg/release/sdk.go b/pkg/release/sdk.go index 4b91fac..6eac536 100644 --- a/pkg/release/sdk.go +++ b/pkg/release/sdk.go @@ -40,7 +40,7 @@ func RunSDK(ctx context.Context, cfg *Config, dryRun bool) (*SDKRelease, error) version := cfg.version if version == "" { var err error - version, err = DetermineVersion(projectDir) + version, err = DetermineVersionWithContext(ctx, projectDir) if err != nil { return nil, coreerr.E("release.RunSDK", "failed to determine version", err) } @@ -48,8 +48,11 @@ func RunSDK(ctx context.Context, cfg *Config, dryRun bool) (*SDKRelease, error) // Run diff check if enabled if cfg.SDK.Diff.Enabled { - breaking, err := checkBreakingChanges(projectDir, cfg.SDK) + breaking, err := checkBreakingChanges(ctx, projectDir, cfg.SDK) if err != nil { + if ctx.Err() != nil { + return nil, coreerr.E("release.RunSDK", "diff check cancelled", ctx.Err()) + } // Non-fatal: warn and continue core.Print(nil, "Warning: diff check failed: %v", err) } else if breaking { @@ -89,9 +92,9 @@ func RunSDK(ctx context.Context, cfg *Config, dryRun bool) (*SDKRelease, error) } // checkBreakingChanges runs oasdiff to detect breaking changes. -func checkBreakingChanges(projectDir string, cfg *SDKConfig) (bool, error) { +func checkBreakingChanges(ctx context.Context, projectDir string, cfg *SDKConfig) (bool, error) { // Get previous tag for comparison (uses getPreviousTag from changelog.go) - prevTag, err := getPreviousTag(projectDir, "HEAD") + prevTag, err := getPreviousTagWithContext(ctx, projectDir, "HEAD") if err != nil { return false, coreerr.E("release.checkBreakingChanges", "no previous tag found", err) } diff --git a/pkg/release/version.go b/pkg/release/version.go index 0b5d601..3f57d1d 100644 --- a/pkg/release/version.go +++ b/pkg/release/version.go @@ -22,14 +22,31 @@ var semverRegex = regexp.MustCompile(`^v?(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.-]+) // // Usage example: call release.DetermineVersion(...) from integrating code. func DetermineVersion(dir string) (string, error) { + return DetermineVersionWithContext(context.Background(), dir) +} + +// DetermineVersionWithContext determines the version while honouring caller cancellation. +// It checks in order: +// 1. Git tag on HEAD +// 2. Most recent tag + increment patch +// 3. Default to v0.0.1 if no tags exist +// +// Usage example: call release.DetermineVersionWithContext(...) from integrating code. +func DetermineVersionWithContext(ctx context.Context, dir string) (string, error) { // Check if HEAD has a tag - headTag, err := getTagOnHead(dir) + headTag, err := getTagOnHeadWithContext(ctx, dir) if err == nil && headTag != "" { return normalizeVersion(headTag), nil } + if err != nil && ctx.Err() != nil { + return "", coreerr.E("release.DetermineVersionWithContext", "version lookup cancelled", ctx.Err()) + } // Get most recent tag - latestTag, err := getLatestTag(dir) + latestTag, err := getLatestTagWithContext(ctx, dir) + if err != nil && ctx.Err() != nil { + return "", coreerr.E("release.DetermineVersionWithContext", "version lookup cancelled", ctx.Err()) + } if err != nil || latestTag == "" { // No tags exist, return default return "v0.0.1", nil @@ -138,7 +155,11 @@ func normalizeVersion(version string) string { // getTagOnHead returns the tag on HEAD, if any. func getTagOnHead(dir string) (string, error) { - output, err := ax.RunDir(context.Background(), dir, "git", "describe", "--tags", "--exact-match", "HEAD") + return getTagOnHeadWithContext(context.Background(), dir) +} + +func getTagOnHeadWithContext(ctx context.Context, dir string) (string, error) { + output, err := ax.RunDir(ctx, dir, "git", "describe", "--tags", "--exact-match", "HEAD") if err != nil { return "", err } @@ -147,7 +168,11 @@ func getTagOnHead(dir string) (string, error) { // getLatestTag returns the most recent tag in the repository. func getLatestTag(dir string) (string, error) { - output, err := ax.RunDir(context.Background(), dir, "git", "describe", "--tags", "--abbrev=0") + return getLatestTagWithContext(context.Background(), dir) +} + +func getLatestTagWithContext(ctx context.Context, dir string) (string, error) { + output, err := ax.RunDir(ctx, dir, "git", "describe", "--tags", "--abbrev=0") if err != nil { return "", err } diff --git a/pkg/release/version_test.go b/pkg/release/version_test.go index 50d23fd..052de6f 100644 --- a/pkg/release/version_test.go +++ b/pkg/release/version_test.go @@ -1,6 +1,7 @@ package release import ( + "context" "testing" "dappco.re/go/core/build/internal/ax" @@ -109,6 +110,19 @@ func TestVersion_DetermineVersion_Bad(t *testing.T) { require.NoError(t, err) assert.Equal(t, "v0.0.1", version) }) + + t.Run("returns error when context is cancelled", func(t *testing.T) { + dir := setupGitRepo(t) + createCommit(t, dir, "feat: initial commit") + createTag(t, dir, "v1.0.0") + + ctx, cancel := context.WithCancel(context.Background()) + cancel() + + _, err := DetermineVersionWithContext(ctx, dir) + require.Error(t, err) + assert.ErrorIs(t, err, context.Canceled) + }) } func TestVersion_GetTagOnHead_Good(t *testing.T) {