Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/actions/extension-check/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: "Extension Check"
description: "Lint, typecheck, test, and compile the VS Code extension"

runs:
using: "composite"
steps:
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: vscode-gotest/package-lock.json
- run: npm ci
shell: bash
working-directory: vscode-gotest
- run: npm run format:check
shell: bash
working-directory: vscode-gotest
- run: npx tsc --noEmit
shell: bash
working-directory: vscode-gotest
- run: npm test
shell: bash
working-directory: vscode-gotest
- run: npm run compile
shell: bash
working-directory: vscode-gotest
15 changes: 0 additions & 15 deletions .github/actions/setup-gotest/action.yml

This file was deleted.

11 changes: 1 addition & 10 deletions .github/workflows/extension-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: vscode-gotest/package-lock.json
- run: npm ci
- run: npm run format:check
- run: npx tsc --noEmit
- run: npm test
- run: npm run compile
- uses: ./.github/actions/extension-check

package:
runs-on: ubuntu-latest
Expand Down
11 changes: 1 addition & 10 deletions .github/workflows/extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
cache-dependency-path: vscode-gotest/package-lock.json
- run: npm ci
- run: npm run format:check
- run: npx tsc --noEmit
- run: npm test
- run: npm run compile
- uses: ./.github/actions/extension-check

package:
runs-on: ubuntu-latest
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: "1.26"
- name: Init workspace
run: go work init . ./examples
- name: Format check
run: test -z "$(gofmt -l .)" || (echo "gofmt needed on:" && gofmt -l . && exit 1)
- name: Vet
Expand Down
2 changes: 0 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: stable
- name: Init workspace
run: go work init . ./examples
- run: go vet ./... ./examples/...
- run: go test -ldflags=-checklinkname=0 ./... -race
- run: go run ./cmd/gotest spec --no-color --min=40 ./... ./examples/... -race
Expand Down
17 changes: 0 additions & 17 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,6 @@ concurrency:
cancel-in-progress: true

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: "1.26"
- run: go build ./...

platform-test:
runs-on: ${{ matrix.os }}
strategy:
Expand All @@ -34,8 +21,6 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: "1.26"
- name: Init workspace
run: go work init . ./examples
- name: Test (stdlib)
run: go test -ldflags=-checklinkname=0 ./... -race
- name: Test (suites)
Expand All @@ -55,8 +40,6 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Init workspace
run: go work init . ./examples
- name: Test (stdlib)
run: go test -ldflags=-checklinkname=0 -coverprofile=coverage-stdlib.out ./... -race
- name: Test (suites)
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
go.work
go.work.sum
bin/
dist/
Expand Down
153 changes: 81 additions & 72 deletions cmd/gotest/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,11 @@ func runTest(inv Invocation) int { //nolint:gocritic // hugeParam: stable API
return runSpec(Invocation{Args: specArgs, Config: inv.Config})
}

args := inv.DefaultArgs()
ownArgs, goTestArgs, err := SplitArgs(args, testAllowed)
ownArgs, goTestArgs, err := SplitArgs(inv.DefaultArgs(), testAllowed)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
return 2
}

jsonMode, goTestArgs := stripJSONFlag(goTestArgs)

minCoverage, err := parseMinFlag(ownArgs)
Expand All @@ -98,84 +96,22 @@ func runTest(inv Invocation) int { //nolint:gocritic // hugeParam: stable API
if minCoverage == 0 {
minCoverage = inv.Config.MinCoverage
}
setupTimeout, err := parseSetupTimeoutFlag(ownArgs)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
return 2
}
globalTimeout, err := parseGlobalTimeoutFlag(ownArgs)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
return 2
}
globalTimeout = resolveGlobalTimeout(globalTimeout)
parallel, err := parseParallelFlag(ownArgs)

goTestArgs, coverProfile, coverCleanup, err := ensureCoverProfile(goTestArgs, minCoverage)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
return 2
}
if parallel == 0 {
parallel = inv.Config.Parallel
}
compileParallel, err := parseCompileParallelFlag(ownArgs)
defer coverCleanup()

cfg, err := parseExecFlags(ownArgs, goTestArgs, &inv.Config)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
return 2
}
if compileParallel == 0 {
compileParallel = inv.Config.CompileParallel
}

var coverProfile string
if minCoverage > 0 {
for _, arg := range goTestArgs {
if v, ok := strings.CutPrefix(arg, "-coverprofile="); ok {
coverProfile = v
}
}
if coverProfile == "" {
f, err := os.CreateTemp("", "gotest-cover-*.out")
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: %s\n", err)
return 2
}
coverProfile = f.Name()
f.Close()
defer os.Remove(coverProfile)
goTestArgs = append(goTestArgs, "-coverprofile="+coverProfile)
}
}

patterns := ExtractPackagePatterns(goTestArgs)
cfg := ExecConfig{
GoTestArgs: goTestArgs,
PackagePatterns: patterns,
SetupTimeout: setupTimeout,
GlobalTimeout: globalTimeout,
Debug: slices.Contains(ownArgs, "--debug"),
CI: slices.Contains(ownArgs, "--ci"),
JSON: jsonMode,
UpdateSnapshots: slices.Contains(ownArgs, "--update-snapshots"),
NoCache: slices.Contains(ownArgs, "--no-cache"),
Parallel: parallel,
CompileParallel: compileParallel,
}

code := Run(cfg)
cfg.JSON = jsonMode

if code == 0 && minCoverage > 0 {
pct, err := readCoverageTotal(coverProfile)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: reading coverage: %s\n", err)
return 2
}
if pct < float64(minCoverage) {
fmt.Fprintf(os.Stderr, "\nFAIL: %.1f%% coverage (minimum %d%%)\n", pct, minCoverage)
return 1
}
}

return code
return enforceCoverage(coverProfile, minCoverage, Run(cfg))
}

func parseMinFlag(args []string) (int, error) {
Expand Down Expand Up @@ -252,6 +188,79 @@ func parseCompileParallelFlag(args []string) (int, error) {
return v, nil
}

func parseExecFlags(ownArgs, goTestArgs []string, projCfg *config.ProjectConfig) (ExecConfig, error) {
setupTimeout, err := parseSetupTimeoutFlag(ownArgs)
if err != nil {
return ExecConfig{}, err
}
globalTimeout, err := parseGlobalTimeoutFlag(ownArgs)
if err != nil {
return ExecConfig{}, err
}
globalTimeout = resolveGlobalTimeout(globalTimeout)
parallel, err := parseParallelFlag(ownArgs)
if err != nil {
return ExecConfig{}, err
}
if parallel == 0 {
parallel = projCfg.Parallel
}
compileParallel, err := parseCompileParallelFlag(ownArgs)
if err != nil {
return ExecConfig{}, err
}
if compileParallel == 0 {
compileParallel = projCfg.CompileParallel
}
return ExecConfig{
GoTestArgs: goTestArgs,
PackagePatterns: ExtractPackagePatterns(goTestArgs),
SetupTimeout: setupTimeout,
GlobalTimeout: globalTimeout,
Debug: slices.Contains(ownArgs, "--debug"),
CI: slices.Contains(ownArgs, "--ci"),
UpdateSnapshots: slices.Contains(ownArgs, "--update-snapshots"),
NoCache: slices.Contains(ownArgs, "--no-cache"),
Parallel: parallel,
CompileParallel: compileParallel,
}, nil
}

func ensureCoverProfile(goTestArgs []string, minCoverage int) ([]string, string, func(), error) {
noop := func() {}
if minCoverage <= 0 {
return goTestArgs, "", noop, nil
}
for _, arg := range goTestArgs {
if v, ok := strings.CutPrefix(arg, "-coverprofile="); ok {
return goTestArgs, v, noop, nil
}
}
f, err := os.CreateTemp("", "gotest-cover-*.out")
if err != nil {
return goTestArgs, "", noop, err
}
profile := f.Name()
f.Close()
return append(goTestArgs, "-coverprofile="+profile), profile, func() { os.Remove(profile) }, nil
}

func enforceCoverage(coverProfile string, minCoverage, code int) int {
if code != 0 || minCoverage <= 0 || coverProfile == "" {
return code
}
pct, err := readCoverageTotal(coverProfile)
if err != nil {
fmt.Fprintf(os.Stderr, "FAIL: reading coverage: %s\n", err)
return 2
}
if pct < float64(minCoverage) {
fmt.Fprintf(os.Stderr, "\nFAIL: %.1f%% coverage (minimum %d%%)\n", pct, minCoverage)
return 1
}
return code
}

func readCoverageTotal(profilePath string) (float64, error) {
out, err := exec.Command("go", "tool", "cover", "-func="+profilePath).Output() //nolint:gosec // G204: go tool with controlled arguments
if err != nil {
Expand Down
Loading
Loading