mirror of
https://github.com/temporalio/temporal.git
synced 2026-08-30 18:41:49 -07:00
Rewrite dependency version check as Go tool, extend to main branch (#9816)
Rewrites the release dependency check as a Go tool and extends it to cover the main branch. The original check was a shell script using `grep`/`awk` to extract versions from `go.mod`. Moving to Go lets us use `golang.org/x/mod/modfile` (proper AST parsing), `module.IsPseudoVersion`/`PseudoVersionRev` (pseudo-version decomposition), and `semver.IsValid` — none of which are feasible to replicate reliably in shell. Using a Go tool is also consistent with the pattern in `cmd/tools/`. The rewrite also extends validation: the original script only enforced tagged releases on `release/*` and `cloud/*` branches. The new tool adds a `main` branch policy: pseudo-versions are allowed on main, but the referenced commit must be on the dependency's default branch (not a feature branch or a fork). ## Policies enforced - `release/*` and `cloud/*`: must be tagged semver releases - `main`: tagged releases accepted; pseudo-versions must reference a commit on the dependency's default branch - other branches: skipped ## Why If an API or SDK references a commit that's not on the main branch or a tag, it creates problems when bumping the version later on. There was a recent occurrence of this. ## Running locally ``` go run ./cmd/tools/check-dependencies --base-branch main ``` Pass the branch you're targeting as `--base-branch`. For example, to simulate a PR against a release branch: ``` go run ./cmd/tools/check-dependencies --base-branch release/v1.31 ```
This commit is contained in:
60
.github/workflows/check-release-dependencies.yml
vendored
60
.github/workflows/check-release-dependencies.yml
vendored
@@ -1,6 +1,10 @@
|
||||
name: Check Release Dependencies
|
||||
on:
|
||||
pull_request: {}
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
- "release/**"
|
||||
- "cloud/**"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -11,49 +15,15 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
if: >-
|
||||
startsWith('release/', github.event.pull_request.base.ref) ||
|
||||
startsWith('cloud/', github.event.pull_request.base.ref)
|
||||
|
||||
- name: Check temporal dependencies use tagged versions
|
||||
if: >-
|
||||
startsWith('release/', github.event.pull_request.base.ref) ||
|
||||
startsWith('cloud/', github.event.pull_request.base.ref)
|
||||
run: |
|
||||
echo "Checking that temporal dependencies use tagged versions..."
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
check-latest: true
|
||||
cache: true
|
||||
|
||||
# Semantic version regex pattern (e.g., v1.2.3)
|
||||
SEMVER_PATTERN="^v[0-9]+\.[0-9]+\.[0-9]+$"
|
||||
|
||||
DEPENDENCIES=(
|
||||
"go.temporal.io/api"
|
||||
"go.temporal.io/sdk"
|
||||
)
|
||||
|
||||
ERRORS=""
|
||||
|
||||
for DEPENDENCY in "${DEPENDENCIES[@]}"; do
|
||||
VERSION=$(grep "^[[:space:]]*$DEPENDENCY" go.mod | awk '{print $2}')
|
||||
|
||||
if [ -z "$VERSION" ]; then
|
||||
echo "Error: $DEPENDENCY dependency not found in go.mod"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! echo "$VERSION" | grep -qE "$SEMVER_PATTERN"; then
|
||||
ERRORS="${ERRORS} $DEPENDENCY version '$VERSION' is not using a tagged version\n"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$ERRORS" ]; then
|
||||
echo "Dependency version check failed:"
|
||||
echo -e "$ERRORS"
|
||||
echo ""
|
||||
echo "For release branches, temporal dependencies must point to tagged"
|
||||
echo "versions (e.g., v1.2.3) rather than specific commits."
|
||||
echo ""
|
||||
echo "Please update your go.mod file to use proper semantic version tags."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All temporal dependencies are using tagged versions"
|
||||
- name: Validate dependency versions for PR base branch
|
||||
run: >-
|
||||
go run ./cmd/tools/check-dependencies
|
||||
--base-branch "${{ github.event.pull_request.base.ref }}"
|
||||
|
||||
225
cmd/tools/check-dependencies/main.go
Normal file
225
cmd/tools/check-dependencies/main.go
Normal file
@@ -0,0 +1,225 @@
|
||||
// check-dependencies validates that key Go module dependencies (go.temporal.io/api
|
||||
// and go.temporal.io/sdk) meet version policies for the PR's base branch:
|
||||
//
|
||||
// - release/* and cloud/* branches: dependencies must be tagged semver releases.
|
||||
// - main: tagged releases are accepted; pseudo-versions must reference a commit
|
||||
// on the dependency's default branch.
|
||||
// - Other branches: no policy enforced.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
"golang.org/x/mod/module"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
const defaultGoModPath = "go.mod"
|
||||
|
||||
type moduleSpec struct {
|
||||
modulePath string
|
||||
repoURL string
|
||||
defaultBranch string
|
||||
}
|
||||
|
||||
var knownModules = []moduleSpec{
|
||||
{
|
||||
modulePath: "go.temporal.io/api",
|
||||
repoURL: "https://github.com/temporalio/api-go.git",
|
||||
defaultBranch: "master",
|
||||
},
|
||||
{
|
||||
modulePath: "go.temporal.io/sdk",
|
||||
repoURL: "https://github.com/temporalio/sdk-go.git",
|
||||
defaultBranch: "master",
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
baseBranch := flag.String("base-branch", "", "PR base branch (e.g. main, release/v1.31)")
|
||||
goModPath := flag.String("go-mod", defaultGoModPath, "Path to go.mod")
|
||||
flag.Parse()
|
||||
|
||||
branch := strings.TrimSpace(*baseBranch)
|
||||
if branch == "" {
|
||||
fmt.Fprintln(os.Stderr, "Error: base branch is required; pass --base-branch")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
modPath := strings.TrimSpace(*goModPath)
|
||||
goModData, err := os.ReadFile(modPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: failed to read %s: %v\n", modPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
modFile, err := modfile.Parse(modPath, goModData, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: failed to parse %s: %v\n", modPath, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var validateErr error
|
||||
switch {
|
||||
case strings.HasPrefix(branch, "release/") || strings.HasPrefix(branch, "cloud/"):
|
||||
validateErr = validateReleaseBranch(modFile)
|
||||
case branch == "main":
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Minute)
|
||||
defer cancel()
|
||||
validateErr = validateMainBranch(ctx, modFile)
|
||||
default:
|
||||
fmt.Printf("No dependency policy for base branch %q; skipping validation\n", branch)
|
||||
}
|
||||
|
||||
if validateErr != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error: %v\n", validateErr)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func validateReleaseBranch(modFile *modfile.File) error {
|
||||
var failures []string
|
||||
for _, mod := range knownModules {
|
||||
modVersion, ok := findRequiredModuleVersion(modFile, mod.modulePath)
|
||||
if !ok {
|
||||
failures = append(failures, fmt.Sprintf("%s: dependency not found in go.mod", mod.modulePath))
|
||||
continue
|
||||
}
|
||||
|
||||
if !semver.IsValid(modVersion.Version) || module.IsPseudoVersion(modVersion.Version) {
|
||||
failures = append(failures, fmt.Sprintf("%s: version %q must be a tagged semver release", mod.modulePath, modVersion.Version))
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf(" - %s@%s (ok)\n", mod.modulePath, modVersion.Version)
|
||||
}
|
||||
|
||||
if len(failures) > 0 {
|
||||
return fmt.Errorf("release dependency validation failed:\n - %s", strings.Join(failures, "\n - "))
|
||||
}
|
||||
|
||||
fmt.Println("All required dependencies use tagged releases")
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateMainBranch(
|
||||
ctx context.Context,
|
||||
modFile *modfile.File,
|
||||
) error {
|
||||
var failures []string
|
||||
for _, mod := range knownModules {
|
||||
if err := validateMainModule(ctx, modFile, mod); err != nil {
|
||||
failures = append(failures, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
if len(failures) > 0 {
|
||||
return fmt.Errorf("main branch dependency validation failed:\n - %s", strings.Join(failures, "\n - "))
|
||||
}
|
||||
|
||||
fmt.Println("All required dependencies are valid for main branch")
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateMainModule(
|
||||
ctx context.Context,
|
||||
modFile *modfile.File,
|
||||
mod moduleSpec,
|
||||
) error {
|
||||
modVersion, ok := findRequiredModuleVersion(modFile, mod.modulePath)
|
||||
if !ok {
|
||||
return fmt.Errorf("%s: dependency not found in go.mod", mod.modulePath)
|
||||
}
|
||||
version := modVersion.Version
|
||||
|
||||
fmt.Printf("Found %s version: %s\n", mod.modulePath, version)
|
||||
|
||||
if !module.IsPseudoVersion(version) {
|
||||
if !semver.IsValid(version) {
|
||||
return fmt.Errorf("%s@%s: not a valid semver tag", mod.modulePath, version)
|
||||
}
|
||||
fmt.Printf(" - %s@%s is a tagged release (ok)\n", mod.modulePath, version)
|
||||
return nil
|
||||
}
|
||||
|
||||
shortHash, err := module.PseudoVersionRev(version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s@%s: failed to parse pseudo-version revision: %v", mod.modulePath, version, err)
|
||||
}
|
||||
|
||||
onDefault, err := resolveModuleOriginForSpec(ctx, mod, shortHash)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%s@%s: failed to resolve module origin: %v", mod.modulePath, version, err)
|
||||
}
|
||||
|
||||
if !onDefault {
|
||||
return fmt.Errorf("%s@%s: commit %s is not on the default branch (%s) of %s",
|
||||
mod.modulePath, version, shortHash, mod.defaultBranch, mod.repoURL)
|
||||
}
|
||||
|
||||
fmt.Printf(" - %s@%s is on %s (ok)\n", mod.modulePath, version, mod.defaultBranch)
|
||||
return nil
|
||||
}
|
||||
|
||||
func findRequiredModuleVersion(modFile *modfile.File, modulePath string) (module.Version, bool) {
|
||||
for _, req := range modFile.Require {
|
||||
if req.Mod.Path == modulePath {
|
||||
return req.Mod, true
|
||||
}
|
||||
}
|
||||
return module.Version{}, false
|
||||
}
|
||||
|
||||
// resolveModuleOriginForSpec reports whether shortHash is reachable from the
|
||||
// default branch of mod's repository.
|
||||
//
|
||||
// It runs two git commands:
|
||||
//
|
||||
// 1. git clone --bare --filter=blob:none --single-branch --branch <defaultBranch> <repoURL> <tmpDir>
|
||||
// --bare: clone without a working tree; only the git object store and refs
|
||||
// are written to tmpDir.
|
||||
// --filter=blob:none: partial clone — fetch commits and trees but skip file
|
||||
// blobs entirely, since we only need commit graph reachability.
|
||||
// --single-branch: fetch only the ref for --branch, not all remote branches.
|
||||
// --branch <defaultBranch>: which branch to fetch.
|
||||
//
|
||||
// 2. git -C <tmpDir> merge-base --is-ancestor <shortHash> refs/heads/<defaultBranch>
|
||||
// -C <tmpDir>: run in the cloned bare repo.
|
||||
// merge-base --is-ancestor: tests reachability rather than finding a common
|
||||
// ancestor — exits 0 if <shortHash> is an ancestor of (or equal to) the
|
||||
// branch tip, exits 1 if it is not.
|
||||
// <shortHash>: the abbreviated commit hash extracted from the pseudo-version.
|
||||
// refs/heads/<defaultBranch>: the branch tip to check ancestry against.
|
||||
// Any other exit code indicates an error (e.g. the object does not exist).
|
||||
func resolveModuleOriginForSpec(ctx context.Context, mod moduleSpec, shortHash string) (bool, error) {
|
||||
tmpRepo, err := os.MkdirTemp("", "check-dependencies-*")
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to create temp repo dir: %w", err)
|
||||
}
|
||||
defer func() { _ = os.RemoveAll(tmpRepo) }()
|
||||
|
||||
cmd := exec.CommandContext(ctx, "git", "clone", "--bare", "--filter=blob:none", "--single-branch", "--branch", mod.defaultBranch, mod.repoURL, tmpRepo)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("git clone failed: %w: %s", err, strings.TrimSpace(string(out)))
|
||||
}
|
||||
|
||||
out, err = exec.CommandContext(ctx, "git", "-C", tmpRepo, "merge-base", "--is-ancestor", shortHash, "refs/heads/"+mod.defaultBranch).CombinedOutput()
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
var exitErr *exec.ExitError
|
||||
if errors.As(err, &exitErr) && exitErr.ExitCode() == 1 {
|
||||
return false, nil
|
||||
}
|
||||
fmt.Printf("git merge-base --is-ancestor output: %s\n", strings.TrimSpace(string(out)))
|
||||
return false, fmt.Errorf("git merge-base --is-ancestor failed: %w", err)
|
||||
}
|
||||
252
cmd/tools/check-dependencies/main_test.go
Normal file
252
cmd/tools/check-dependencies/main_test.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/mod/modfile"
|
||||
)
|
||||
|
||||
func parseGoMod(t *testing.T, content string) *modfile.File {
|
||||
t.Helper()
|
||||
f, err := modfile.Parse("go.mod", []byte(content), nil)
|
||||
require.NoError(t, err)
|
||||
return f
|
||||
}
|
||||
|
||||
func makeGoMod(deps map[string]string) string {
|
||||
s := "module test\n\ngo 1.21\n\nrequire (\n"
|
||||
for mod, ver := range deps {
|
||||
s += fmt.Sprintf("\t%s %s\n", mod, ver)
|
||||
}
|
||||
return s + ")\n"
|
||||
}
|
||||
|
||||
func TestFindRequiredModuleVersion(t *testing.T) {
|
||||
f := parseGoMod(t, makeGoMod(map[string]string{
|
||||
"go.temporal.io/api": "v1.2.3",
|
||||
"go.temporal.io/sdk": "v1.4.0",
|
||||
}))
|
||||
|
||||
t.Run("found", func(t *testing.T) {
|
||||
v, ok := findRequiredModuleVersion(f, "go.temporal.io/api")
|
||||
require.True(t, ok)
|
||||
require.Equal(t, "v1.2.3", v.Version)
|
||||
})
|
||||
|
||||
t.Run("not found", func(t *testing.T) {
|
||||
_, ok := findRequiredModuleVersion(f, "go.temporal.io/missing")
|
||||
require.False(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidateReleaseBranch(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
deps map[string]string
|
||||
wantErr bool
|
||||
errContains []string
|
||||
errNotContains []string
|
||||
}{
|
||||
{
|
||||
name: "tagged semver passes",
|
||||
deps: map[string]string{
|
||||
"go.temporal.io/api": "v1.40.0",
|
||||
"go.temporal.io/sdk": "v1.31.0",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pseudo-version fails",
|
||||
deps: map[string]string{
|
||||
"go.temporal.io/api": "v1.40.1-0.20240101000000-abcdef012345",
|
||||
"go.temporal.io/sdk": "v1.31.0",
|
||||
},
|
||||
wantErr: true,
|
||||
errContains: []string{"go.temporal.io/api", "tagged semver release"},
|
||||
},
|
||||
{
|
||||
name: "both modules missing fails",
|
||||
deps: nil, // empty go.mod
|
||||
wantErr: true,
|
||||
errContains: []string{"go.temporal.io/api", "go.temporal.io/sdk"},
|
||||
},
|
||||
{
|
||||
name: "one pseudo one tagged fails with one error",
|
||||
deps: map[string]string{
|
||||
"go.temporal.io/api": "v1.40.0",
|
||||
"go.temporal.io/sdk": "v1.31.1-0.20240101000000-abcdef012345",
|
||||
},
|
||||
wantErr: true,
|
||||
errContains: []string{"go.temporal.io/sdk"},
|
||||
errNotContains: []string{"go.temporal.io/api"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var content string
|
||||
if tc.deps == nil {
|
||||
content = "module test\n\ngo 1.21\n"
|
||||
} else {
|
||||
content = makeGoMod(tc.deps)
|
||||
}
|
||||
f := parseGoMod(t, content)
|
||||
err := validateReleaseBranch(f)
|
||||
if !tc.wantErr {
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
require.Error(t, err)
|
||||
for _, s := range tc.errContains {
|
||||
require.Contains(t, err.Error(), s)
|
||||
}
|
||||
for _, s := range tc.errNotContains {
|
||||
require.NotContains(t, err.Error(), s)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// localRepo is a bare git repo with commits for testing.
|
||||
type localRepo struct {
|
||||
// Path to the bare repo.
|
||||
path string
|
||||
// Hash of the commit on the default branch.
|
||||
onBranchHash string
|
||||
// Hash of a commit that exists in the repo but is NOT on the default branch.
|
||||
offBranchHash string
|
||||
}
|
||||
|
||||
// initLocalRepo creates a bare git repo with one commit on the default branch
|
||||
// and one commit on a side branch. Both commits exist as objects in the bare
|
||||
// repo, but only onBranchHash is reachable from refs/heads/<branch>.
|
||||
func initLocalRepo(t *testing.T, branch string) localRepo {
|
||||
t.Helper()
|
||||
|
||||
work := t.TempDir()
|
||||
run := func(args ...string) string {
|
||||
t.Helper()
|
||||
cmd := exec.Command("git", args...)
|
||||
cmd.Dir = work
|
||||
out, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, "git %v: %s", args, out)
|
||||
return string(out)
|
||||
}
|
||||
|
||||
run("init", "-b", branch)
|
||||
run("config", "user.email", "test@test.com")
|
||||
run("config", "user.name", "Test")
|
||||
|
||||
require.NoError(t, os.WriteFile(filepath.Join(work, "file.txt"), []byte("hello"), 0o600))
|
||||
run("add", ".")
|
||||
run("commit", "-m", "initial")
|
||||
onHash := run("rev-parse", "HEAD")
|
||||
|
||||
// Create a side branch with its own commit.
|
||||
run("checkout", "-b", "side")
|
||||
require.NoError(t, os.WriteFile(filepath.Join(work, "side.txt"), []byte("side"), 0o600))
|
||||
run("add", ".")
|
||||
run("commit", "-m", "side commit")
|
||||
offHash := run("rev-parse", "HEAD")
|
||||
run("checkout", branch)
|
||||
|
||||
// Clone to a bare repo without --single-branch so that git fetches all
|
||||
// branches, making the side-branch commit reachable as an object. This
|
||||
// mirrors the scenario where a pseudo-version references a commit that
|
||||
// exists in the repo but is not on the default branch.
|
||||
bare := t.TempDir()
|
||||
cmd := exec.Command("git", "clone", "--bare", work, bare)
|
||||
out, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, "git clone --bare: %s", out)
|
||||
|
||||
return localRepo{
|
||||
path: bare,
|
||||
onBranchHash: onHash[:len(onHash)-1],
|
||||
offBranchHash: offHash[:len(offHash)-1],
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveModuleOriginForSpec(t *testing.T) {
|
||||
const branch = "master"
|
||||
repo := initLocalRepo(t, branch)
|
||||
|
||||
spec := moduleSpec{
|
||||
modulePath: "go.temporal.io/api",
|
||||
repoURL: repo.path,
|
||||
defaultBranch: branch,
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
hash string
|
||||
onDefault bool
|
||||
}{
|
||||
{"commit on default branch", repo.onBranchHash[:12], true},
|
||||
{"commit not on default branch", repo.offBranchHash[:12], false},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
onDefault, err := resolveModuleOriginForSpec(context.Background(), spec, tc.hash)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.onDefault, onDefault)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// setupLocalKnownModules replaces knownModules with specs pointing at the local
|
||||
// bare repo, restoring the original on cleanup.
|
||||
func setupLocalKnownModules(t *testing.T, repo localRepo, branch string) {
|
||||
t.Helper()
|
||||
orig := knownModules
|
||||
t.Cleanup(func() { knownModules = orig })
|
||||
knownModules = []moduleSpec{
|
||||
{modulePath: "go.temporal.io/api", repoURL: repo.path, defaultBranch: branch},
|
||||
{modulePath: "go.temporal.io/sdk", repoURL: repo.path, defaultBranch: branch},
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateMainBranch(t *testing.T) {
|
||||
t.Run("tagged release passes", func(t *testing.T) {
|
||||
f := parseGoMod(t, makeGoMod(map[string]string{
|
||||
"go.temporal.io/api": "v1.40.0",
|
||||
"go.temporal.io/sdk": "v1.31.0",
|
||||
}))
|
||||
require.NoError(t, validateMainBranch(context.Background(), f))
|
||||
})
|
||||
|
||||
t.Run("missing module fails", func(t *testing.T) {
|
||||
f := parseGoMod(t, "module test\n\ngo 1.21\n")
|
||||
err := validateMainBranch(context.Background(), f)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "go.temporal.io/api")
|
||||
})
|
||||
|
||||
const branch = "master"
|
||||
repo := initLocalRepo(t, branch)
|
||||
setupLocalKnownModules(t, repo, branch)
|
||||
|
||||
t.Run("pseudo-version on default branch passes", func(t *testing.T) {
|
||||
ver := fmt.Sprintf("v0.0.0-20240101000000-%s", repo.onBranchHash[:12])
|
||||
f := parseGoMod(t, makeGoMod(map[string]string{
|
||||
"go.temporal.io/api": ver,
|
||||
"go.temporal.io/sdk": ver,
|
||||
}))
|
||||
require.NoError(t, validateMainBranch(context.Background(), f))
|
||||
})
|
||||
|
||||
t.Run("pseudo-version not on default branch fails", func(t *testing.T) {
|
||||
ver := fmt.Sprintf("v0.0.0-20240101000000-%s", repo.offBranchHash[:12])
|
||||
f := parseGoMod(t, makeGoMod(map[string]string{
|
||||
"go.temporal.io/api": ver,
|
||||
"go.temporal.io/sdk": ver,
|
||||
}))
|
||||
err := validateMainBranch(context.Background(), f)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "not on the default branch")
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user