feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
package builders
|
|
|
|
|
|
|
|
|
|
import (
|
2026-04-01 14:20:05 +00:00
|
|
|
"context"
|
2026-04-01 14:41:36 +00:00
|
|
|
"os"
|
2026-04-01 16:29:30 +00:00
|
|
|
"runtime"
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
"testing"
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
"dappco.re/go/core/build/internal/ax"
|
|
|
|
|
|
2026-03-22 01:53:16 +00:00
|
|
|
"dappco.re/go/core/build/pkg/build"
|
|
|
|
|
"dappco.re/go/core/io"
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
)
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderName_Good(t *testing.T) {
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
assert.Equal(t, "taskfile", builder.Name())
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderDetect_Good(t *testing.T) {
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
fs := io.Local
|
|
|
|
|
|
|
|
|
|
t.Run("detects Taskfile.yml", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
err := ax.WriteFile(ax.Join(dir, "Taskfile.yml"), []byte("version: '3'\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.True(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("detects Taskfile.yaml", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
err := ax.WriteFile(ax.Join(dir, "Taskfile.yaml"), []byte("version: '3'\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.True(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("detects Taskfile (no extension)", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
err := ax.WriteFile(ax.Join(dir, "Taskfile"), []byte("version: '3'\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.True(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("detects lowercase taskfile.yml", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
err := ax.WriteFile(ax.Join(dir, "taskfile.yml"), []byte("version: '3'\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.True(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("detects lowercase taskfile.yaml", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
err := ax.WriteFile(ax.Join(dir, "taskfile.yaml"), []byte("version: '3'\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.True(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("returns false for empty directory", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.False(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("returns false for non-Taskfile project", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
err := ax.WriteFile(ax.Join(dir, "Makefile"), []byte("all:\n\techo hello\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.False(t, detected)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("does not match Taskfile in subdirectory", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
subDir := ax.Join(dir, "subdir")
|
|
|
|
|
require.NoError(t, ax.MkdirAll(subDir, 0755))
|
|
|
|
|
err := ax.WriteFile(ax.Join(subDir, "Taskfile.yml"), []byte("version: '3'\n"), 0644)
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
detected, err := builder.Detect(fs, dir)
|
|
|
|
|
assert.NoError(t, err)
|
|
|
|
|
assert.False(t, detected)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderFindArtifacts_Good(t *testing.T) {
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
fs := io.Local
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
|
|
|
|
|
t.Run("finds files in output directory", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp"), []byte("binary"), 0755))
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp.tar.gz"), []byte("archive"), 0644))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
artifacts := builder.findArtifacts(fs, dir)
|
|
|
|
|
assert.Len(t, artifacts, 2)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("skips hidden files", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp"), []byte("binary"), 0755))
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, ".hidden"), []byte("hidden"), 0644))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
artifacts := builder.findArtifacts(fs, dir)
|
|
|
|
|
assert.Len(t, artifacts, 1)
|
|
|
|
|
assert.Contains(t, artifacts[0].Path, "myapp")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("skips CHECKSUMS.txt", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp"), []byte("binary"), 0755))
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "CHECKSUMS.txt"), []byte("sha256"), 0644))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
artifacts := builder.findArtifacts(fs, dir)
|
|
|
|
|
assert.Len(t, artifacts, 1)
|
|
|
|
|
assert.Contains(t, artifacts[0].Path, "myapp")
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("skips directories", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp"), []byte("binary"), 0755))
|
|
|
|
|
require.NoError(t, ax.MkdirAll(ax.Join(dir, "subdir"), 0755))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
artifacts := builder.findArtifacts(fs, dir)
|
|
|
|
|
assert.Len(t, artifacts, 1)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("returns empty for empty directory", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
|
|
|
|
|
|
|
|
|
artifacts := builder.findArtifacts(fs, dir)
|
|
|
|
|
assert.Empty(t, artifacts)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("returns empty for nonexistent directory", func(t *testing.T) {
|
|
|
|
|
artifacts := builder.findArtifacts(fs, "/nonexistent/path")
|
|
|
|
|
assert.Empty(t, artifacts)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderFindArtifactsForTarget_Good(t *testing.T) {
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
fs := io.Local
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
|
|
|
|
|
t.Run("finds artifacts in platform subdirectory", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
platformDir := ax.Join(dir, "linux_amd64")
|
|
|
|
|
require.NoError(t, ax.MkdirAll(platformDir, 0755))
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(platformDir, "myapp"), []byte("binary"), 0755))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
target := build.Target{OS: "linux", Arch: "amd64"}
|
|
|
|
|
artifacts := builder.findArtifactsForTarget(fs, dir, target)
|
|
|
|
|
assert.Len(t, artifacts, 1)
|
|
|
|
|
assert.Equal(t, "linux", artifacts[0].OS)
|
|
|
|
|
assert.Equal(t, "amd64", artifacts[0].Arch)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("finds artifacts by name pattern in root", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp-linux-amd64"), []byte("binary"), 0755))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
target := build.Target{OS: "linux", Arch: "amd64"}
|
|
|
|
|
artifacts := builder.findArtifactsForTarget(fs, dir, target)
|
|
|
|
|
assert.NotEmpty(t, artifacts)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("returns empty when no matching artifacts", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(dir, "myapp"), []byte("binary"), 0755))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
target := build.Target{OS: "linux", Arch: "arm64"}
|
|
|
|
|
artifacts := builder.findArtifactsForTarget(fs, dir, target)
|
|
|
|
|
assert.Empty(t, artifacts)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("handles .app bundles on darwin", func(t *testing.T) {
|
|
|
|
|
dir := t.TempDir()
|
2026-03-26 17:41:53 +00:00
|
|
|
platformDir := ax.Join(dir, "darwin_arm64")
|
|
|
|
|
appDir := ax.Join(platformDir, "MyApp.app")
|
|
|
|
|
require.NoError(t, ax.MkdirAll(appDir, 0755))
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
|
|
|
|
|
target := build.Target{OS: "darwin", Arch: "arm64"}
|
|
|
|
|
artifacts := builder.findArtifactsForTarget(fs, dir, target)
|
|
|
|
|
assert.Len(t, artifacts, 1)
|
|
|
|
|
assert.Contains(t, artifacts[0].Path, "MyApp.app")
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderMatchPattern_Good(t *testing.T) {
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
|
|
|
|
|
t.Run("matches simple glob", func(t *testing.T) {
|
|
|
|
|
assert.True(t, builder.matchPattern("myapp-linux-amd64", "*-linux-amd64"))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("does not match different pattern", func(t *testing.T) {
|
|
|
|
|
assert.False(t, builder.matchPattern("myapp-linux-amd64", "*-darwin-arm64"))
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("matches wildcard", func(t *testing.T) {
|
|
|
|
|
assert.True(t, builder.matchPattern("test_linux_arm64.bin", "*_linux_arm64*"))
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 17:41:53 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderInterface_Good(t *testing.T) {
|
feat: extract build/, release/, sdk/ from go-devops
Build system (8 builders, signing, archiving), release pipeline
(7 publishers, versioning, changelog), and SDK generation
(OpenAPI diff, code gen). 18K LOC, all tests pass except Go
builder workspace isolation (pre-existing).
Co-Authored-By: Virgil <virgil@lethean.io>
2026-03-09 12:37:36 +00:00
|
|
|
// Verify TaskfileBuilder implements Builder interface
|
|
|
|
|
var _ build.Builder = (*TaskfileBuilder)(nil)
|
|
|
|
|
var _ build.Builder = NewTaskfileBuilder()
|
|
|
|
|
}
|
2026-03-30 01:13:57 +00:00
|
|
|
|
|
|
|
|
func TestTaskfile_TaskfileBuilderResolveTaskCli_Good(t *testing.T) {
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
fallbackDir := t.TempDir()
|
|
|
|
|
fallbackPath := ax.Join(fallbackDir, "task")
|
|
|
|
|
require.NoError(t, ax.WriteFile(fallbackPath, []byte("#!/bin/sh\nexit 0\n"), 0o755))
|
2026-03-30 01:28:57 +00:00
|
|
|
t.Setenv("PATH", "")
|
2026-03-30 01:13:57 +00:00
|
|
|
|
|
|
|
|
command, err := builder.resolveTaskCli(fallbackPath)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Equal(t, fallbackPath, command)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTaskfile_TaskfileBuilderResolveTaskCli_Bad(t *testing.T) {
|
|
|
|
|
builder := NewTaskfileBuilder()
|
2026-03-30 01:28:57 +00:00
|
|
|
t.Setenv("PATH", "")
|
2026-03-30 01:13:57 +00:00
|
|
|
|
|
|
|
|
_, err := builder.resolveTaskCli(ax.Join(t.TempDir(), "missing-task"))
|
|
|
|
|
require.Error(t, err)
|
|
|
|
|
assert.Contains(t, err.Error(), "task CLI not found")
|
|
|
|
|
}
|
2026-04-01 14:20:05 +00:00
|
|
|
|
|
|
|
|
func TestTaskfile_TaskfileBuilderRunTask_Good(t *testing.T) {
|
|
|
|
|
binDir := t.TempDir()
|
|
|
|
|
taskPath := ax.Join(binDir, "task")
|
|
|
|
|
logPath := ax.Join(t.TempDir(), "task.env")
|
|
|
|
|
|
|
|
|
|
script := `#!/bin/sh
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
env | sort > "${TASK_BUILD_LOG_FILE}"
|
|
|
|
|
`
|
|
|
|
|
require.NoError(t, ax.WriteFile(taskPath, []byte(script), 0o755))
|
|
|
|
|
|
|
|
|
|
t.Setenv("TASK_BUILD_LOG_FILE", logPath)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
cfg := &build.Config{
|
|
|
|
|
FS: io.Local,
|
|
|
|
|
ProjectDir: t.TempDir(),
|
|
|
|
|
OutputDir: "/tmp/out",
|
|
|
|
|
Name: "sample",
|
|
|
|
|
Version: "v1.2.3",
|
|
|
|
|
Env: []string{"FOO=bar"},
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 21:05:47 +00:00
|
|
|
require.NoError(t, builder.runTask(context.Background(), cfg, taskPath, cfg.OutputDir, build.Target{OS: "linux", Arch: "amd64"}))
|
2026-04-01 14:20:05 +00:00
|
|
|
|
|
|
|
|
content, err := ax.ReadFile(logPath)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
assert.Contains(t, string(content), "FOO=bar")
|
|
|
|
|
assert.Contains(t, string(content), "GOOS=linux")
|
|
|
|
|
assert.Contains(t, string(content), "GOARCH=amd64")
|
2026-04-01 21:01:13 +00:00
|
|
|
assert.Contains(t, string(content), "TARGET_OS=linux")
|
|
|
|
|
assert.Contains(t, string(content), "TARGET_ARCH=amd64")
|
2026-04-01 14:20:05 +00:00
|
|
|
assert.Contains(t, string(content), "OUTPUT_DIR=/tmp/out")
|
2026-04-01 21:01:13 +00:00
|
|
|
assert.Contains(t, string(content), "TARGET_DIR=/tmp/out/linux_amd64")
|
2026-04-01 14:20:05 +00:00
|
|
|
assert.Contains(t, string(content), "NAME=sample")
|
|
|
|
|
assert.Contains(t, string(content), "VERSION=v1.2.3")
|
2026-04-01 21:13:33 +00:00
|
|
|
assert.Contains(t, string(content), "CGO_ENABLED=0")
|
2026-04-01 14:20:05 +00:00
|
|
|
}
|
2026-04-01 14:41:36 +00:00
|
|
|
|
2026-04-01 21:05:47 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderBuild_DoesNotMutateOutputDir_Good(t *testing.T) {
|
|
|
|
|
projectDir := t.TempDir()
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "Taskfile.yml"), []byte("version: '3'\n"), 0o644))
|
|
|
|
|
|
|
|
|
|
binDir := t.TempDir()
|
|
|
|
|
taskPath := ax.Join(binDir, "task")
|
|
|
|
|
script := `#!/bin/sh
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
mkdir -p "${OUTPUT_DIR}/${GOOS}_${GOARCH}"
|
|
|
|
|
printf '%s\n' "${NAME:-taskfile}" > "${OUTPUT_DIR}/${GOOS}_${GOARCH}/${NAME:-taskfile}"
|
|
|
|
|
`
|
|
|
|
|
require.NoError(t, ax.WriteFile(taskPath, []byte(script), 0o755))
|
|
|
|
|
|
|
|
|
|
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
cfg := &build.Config{
|
|
|
|
|
FS: io.Local,
|
|
|
|
|
ProjectDir: projectDir,
|
|
|
|
|
Name: "sample",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
artifacts, err := builder.Build(context.Background(), cfg, []build.Target{{OS: runtime.GOOS, Arch: runtime.GOARCH}})
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, artifacts, 1)
|
|
|
|
|
assert.Empty(t, cfg.OutputDir)
|
|
|
|
|
assert.Equal(t, ax.Join(projectDir, "dist"), ax.Dir(ax.Dir(artifacts[0].Path)))
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 14:41:36 +00:00
|
|
|
func TestTaskfile_TaskfileBuilderBuild_Good(t *testing.T) {
|
|
|
|
|
projectDir := t.TempDir()
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "Taskfile.yml"), []byte("version: '3'\n"), 0o644))
|
|
|
|
|
|
|
|
|
|
binDir := t.TempDir()
|
|
|
|
|
taskPath := ax.Join(binDir, "task")
|
|
|
|
|
logPath := ax.Join(t.TempDir(), "task.build.env")
|
|
|
|
|
|
|
|
|
|
script := `#!/bin/sh
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
mkdir -p "${OUTPUT_DIR}/${GOOS}_${GOARCH}"
|
|
|
|
|
printf '%s\n' "${NAME:-taskfile}" > "${OUTPUT_DIR}/${GOOS}_${GOARCH}/${NAME:-taskfile}"
|
|
|
|
|
env | sort > "${TASK_BUILD_LOG_FILE}"
|
|
|
|
|
`
|
|
|
|
|
require.NoError(t, ax.WriteFile(taskPath, []byte(script), 0o755))
|
|
|
|
|
|
|
|
|
|
t.Setenv("TASK_BUILD_LOG_FILE", logPath)
|
|
|
|
|
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
cfg := &build.Config{
|
|
|
|
|
FS: io.Local,
|
|
|
|
|
ProjectDir: projectDir,
|
|
|
|
|
Name: "sample",
|
|
|
|
|
Version: "v1.2.3",
|
|
|
|
|
Env: []string{"FOO=bar"},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
artifacts, err := builder.Build(context.Background(), cfg, []build.Target{{OS: "linux", Arch: "amd64"}})
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, artifacts, 1)
|
|
|
|
|
assert.Equal(t, ax.Join(projectDir, "dist", "linux_amd64", "sample"), artifacts[0].Path)
|
|
|
|
|
|
|
|
|
|
content, err := ax.ReadFile(logPath)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Contains(t, string(content), "FOO=bar")
|
|
|
|
|
assert.Contains(t, string(content), "OUTPUT_DIR="+ax.Join(projectDir, "dist"))
|
|
|
|
|
assert.Contains(t, string(content), "GOOS=linux")
|
|
|
|
|
assert.Contains(t, string(content), "GOARCH=amd64")
|
2026-04-01 21:01:13 +00:00
|
|
|
assert.Contains(t, string(content), "TARGET_OS=linux")
|
|
|
|
|
assert.Contains(t, string(content), "TARGET_ARCH=amd64")
|
|
|
|
|
assert.Contains(t, string(content), "TARGET_DIR="+ax.Join(projectDir, "dist", "linux_amd64"))
|
2026-04-01 21:13:33 +00:00
|
|
|
assert.Contains(t, string(content), "CGO_ENABLED=0")
|
2026-04-01 14:41:36 +00:00
|
|
|
}
|
2026-04-01 16:29:30 +00:00
|
|
|
|
|
|
|
|
func TestTaskfile_TaskfileBuilderBuild_DefaultTarget_Good(t *testing.T) {
|
|
|
|
|
projectDir := t.TempDir()
|
|
|
|
|
require.NoError(t, ax.WriteFile(ax.Join(projectDir, "Taskfile.yml"), []byte("version: '3'\n"), 0o644))
|
|
|
|
|
|
|
|
|
|
binDir := t.TempDir()
|
|
|
|
|
taskPath := ax.Join(binDir, "task")
|
|
|
|
|
logPath := ax.Join(t.TempDir(), "task.default.env")
|
|
|
|
|
|
|
|
|
|
script := `#!/bin/sh
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
mkdir -p "${OUTPUT_DIR}/${GOOS}_${GOARCH}"
|
|
|
|
|
printf '%s\n' "${GOOS}/${GOARCH}" > "${OUTPUT_DIR}/${GOOS}_${GOARCH}/artifact"
|
|
|
|
|
env | sort > "${TASK_BUILD_LOG_FILE}"
|
|
|
|
|
`
|
|
|
|
|
require.NoError(t, ax.WriteFile(taskPath, []byte(script), 0o755))
|
|
|
|
|
|
|
|
|
|
t.Setenv("TASK_BUILD_LOG_FILE", logPath)
|
|
|
|
|
t.Setenv("PATH", binDir+string(os.PathListSeparator)+os.Getenv("PATH"))
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
cfg := &build.Config{
|
|
|
|
|
FS: io.Local,
|
|
|
|
|
ProjectDir: projectDir,
|
|
|
|
|
Name: "sample",
|
|
|
|
|
Version: "v1.2.3",
|
|
|
|
|
Env: []string{"FOO=bar"},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
artifacts, err := builder.Build(context.Background(), cfg, nil)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
require.Len(t, artifacts, 1)
|
|
|
|
|
assert.Equal(t, ax.Join(projectDir, "dist", runtime.GOOS+"_"+runtime.GOARCH, "artifact"), artifacts[0].Path)
|
|
|
|
|
assert.Equal(t, runtime.GOOS, artifacts[0].OS)
|
|
|
|
|
assert.Equal(t, runtime.GOARCH, artifacts[0].Arch)
|
|
|
|
|
|
|
|
|
|
content, err := ax.ReadFile(logPath)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
assert.Contains(t, string(content), "FOO=bar")
|
|
|
|
|
assert.Contains(t, string(content), "OUTPUT_DIR="+ax.Join(projectDir, "dist"))
|
|
|
|
|
assert.Contains(t, string(content), "GOOS="+runtime.GOOS)
|
|
|
|
|
assert.Contains(t, string(content), "GOARCH="+runtime.GOARCH)
|
2026-04-01 21:01:13 +00:00
|
|
|
assert.Contains(t, string(content), "TARGET_OS="+runtime.GOOS)
|
|
|
|
|
assert.Contains(t, string(content), "TARGET_ARCH="+runtime.GOARCH)
|
|
|
|
|
assert.Contains(t, string(content), "TARGET_DIR="+ax.Join(projectDir, "dist", runtime.GOOS+"_"+runtime.GOARCH))
|
2026-04-01 21:13:33 +00:00
|
|
|
assert.Contains(t, string(content), "CGO_ENABLED=0")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestTaskfile_TaskfileBuilderRunTask_CGOEnabled_Good(t *testing.T) {
|
|
|
|
|
binDir := t.TempDir()
|
|
|
|
|
taskPath := ax.Join(binDir, "task")
|
|
|
|
|
logPath := ax.Join(t.TempDir(), "task.cgo.env")
|
|
|
|
|
|
|
|
|
|
script := `#!/bin/sh
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
env | sort > "${TASK_BUILD_LOG_FILE}"
|
|
|
|
|
`
|
|
|
|
|
require.NoError(t, ax.WriteFile(taskPath, []byte(script), 0o755))
|
|
|
|
|
|
|
|
|
|
t.Setenv("TASK_BUILD_LOG_FILE", logPath)
|
|
|
|
|
|
|
|
|
|
builder := NewTaskfileBuilder()
|
|
|
|
|
cfg := &build.Config{
|
|
|
|
|
FS: io.Local,
|
|
|
|
|
ProjectDir: t.TempDir(),
|
|
|
|
|
OutputDir: "/tmp/out",
|
|
|
|
|
Name: "sample",
|
|
|
|
|
Version: "v1.2.3",
|
|
|
|
|
CGO: true,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.NoError(t, builder.runTask(context.Background(), cfg, taskPath, cfg.OutputDir, build.Target{OS: "linux", Arch: "amd64"}))
|
|
|
|
|
|
|
|
|
|
content, err := ax.ReadFile(logPath)
|
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
|
|
assert.Contains(t, string(content), "CGO_ENABLED=1")
|
2026-04-01 16:29:30 +00:00
|
|
|
}
|