diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea38d75..e891fce 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -3,7 +3,8 @@ name: Release on: push: tags: - - "v*" # Trigger on version tags like v0.1.0, v1.2.3 + - "v*" + workflow_dispatch: permissions: contents: write # Required for creating releases @@ -11,86 +12,58 @@ permissions: jobs: test: name: Run Tests - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v5 - - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: "1.25" - - - name: Run tests - run: go test -v ./... + uses: ./.github/workflows/run-test.yml + secrets: inherit release: name: Build and Release - needs: test # Only run if tests pass + needs: test runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v5 + uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.25" - - - name: Build binaries for all platforms - run: | - # Get version from tag (GitHub sets GITHUB_REF to refs/tags/v0.1.0) - VERSION=${GITHUB_REF#refs/tags/} - COMMIT=$(git rev-parse --short HEAD) - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') + go-version-file: go.mod - echo "Building version: ${VERSION}" - - # Build flags - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION} -w -s" - - # Create output directory - mkdir -p dist - - # Linux amd64 - echo "Building Linux amd64..." - GOOS=linux GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o dist/devenv-linux-amd64 ./cmd/devenv - - # Linux arm64 - echo "Building Linux arm64..." - GOOS=linux GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o dist/devenv-linux-arm64 ./cmd/devenv - - # macOS amd64 (Intel) - echo "Building macOS amd64..." - GOOS=darwin GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o dist/devenv-darwin-amd64 ./cmd/devenv - - # macOS arm64 (Apple Silicon) - echo "Building macOS arm64..." - GOOS=darwin GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o dist/devenv-darwin-arm64 ./cmd/devenv - - # Windows amd64 - echo "Building Windows amd64..." - GOOS=windows GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o dist/devenv-windows-amd64.exe ./cmd/devenv + - name: Install Task + uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} - echo "✅ All binaries built successfully" - ls -lh dist/ + - name: Build release binaries + run: task build:dist - - name: Generate checksums + # Integration-tested platform: linux/amd64 runs natively in this CI environment. + # All other platforms (linux/arm64, darwin/amd64, darwin/arm64, windows/amd64) + # are cross-compiled only — binaries are published but not executed in CI. + - name: Validate linux/amd64 binary run: | - cd dist - sha256sum * > checksums.txt + VERSION=$(./scripts/get-version.sh) + BINARY=./dist/devenv_${VERSION}_linux_amd64 + + $BINARY version + $BINARY generate valid_user --dry-run --config-dir ./internal/config/testdata - name: Create Release uses: softprops/action-gh-release@v2 with: files: | - dist/devenv-linux-amd64 - dist/devenv-linux-arm64 - dist/devenv-darwin-amd64 - dist/devenv-darwin-arm64 - dist/devenv-windows-amd64.exe + dist/devenv_* dist/checksums.txt + body: | + ## Platform Support + + | Platform | Status | + |---|---| + | linux/amd64 | ✅ Integration-tested | + | linux/arm64 | 🔧 Cross-compiled, not executed in CI | + | darwin/amd64 | 🔧 Cross-compiled, not executed in CI | + | darwin/arm64 | 🔧 Cross-compiled, not executed in CI | + | windows/amd64 | 🔧 Cross-compiled, not executed in CI | generate_release_notes: true draft: false prerelease: false diff --git a/.github/workflows/run-test.yml b/.github/workflows/run-test.yml index a4d7187..24808ab 100644 --- a/.github/workflows/run-test.yml +++ b/.github/workflows/run-test.yml @@ -8,6 +8,7 @@ on: branches: ["main"] pull_request: branches: ["main"] + workflow_call: jobs: build: @@ -18,13 +19,19 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.24" + go-version-file: go.mod + + - name: Install Task + uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Build run: go build -v ./... - name: Test - run: go test -v -race -covermode=atomic -coverprofile=./coverage.out ./... + run: task test:ci - name: Upload coverage reports to Codecov uses: codecov/codecov-action@v5 diff --git a/Taskfile.yml b/Taskfile.yml index 14c28ac..2556f4b 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -4,138 +4,109 @@ vars: BINARY_NAME: devenv SOURCE_DIR: cmd/devenv BUILD_DIR: ./bin + DIST_DIR: ./dist MANIFEST_BUILD_DIR: ./build + VERSION: + sh: ./scripts/get-version.sh + COMMIT: + sh: git rev-parse --short HEAD 2>/dev/null || echo "unknown" + BUILD_TIME: + sh: date -u +'%Y-%m-%dT%H:%M:%SZ' + GO_VERSION: + sh: go version | awk '{print $3}' + LDFLAGS: "-X main.version={{.VERSION}} -X main.gitCommit={{.COMMIT}} -X main.buildTime={{.BUILD_TIME}} -X main.goVersion={{.GO_VERSION}} -w -s" tasks: build: desc: Build devenv binary with version info - env: - VERSION: - sh: ./scripts/get-version.sh cmds: - - | - COMMIT=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') - - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION}" - - echo "Building {{.BUILD_DIR}}/{{.BINARY_NAME}}..." - echo " Version: ${VERSION}" - - go build -ldflags="${LDFLAGS}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}} ./{{.SOURCE_DIR}} - echo "✅ Build complete!" + - mkdir -p {{.BUILD_DIR}} + - go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}} ./{{.SOURCE_DIR}} + - echo "✅ Build complete ({{.VERSION}})" build:release: desc: Build optimized release binary - env: - VERSION: - sh: ./scripts/get-version.sh cmds: - - | - COMMIT=$(git rev-parse --short HEAD) - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION} -w -s" - - mkdir -p {{.BUILD_DIR}} - go build -ldflags="${LDFLAGS}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}} ./{{.SOURCE_DIR}} - echo "✅ Release binary: {{.BUILD_DIR}}/{{.BINARY_NAME}}" + - mkdir -p {{.BUILD_DIR}} + - go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}} ./{{.SOURCE_DIR}} + - echo "✅ Release binary {{.BUILD_DIR}}/{{.BINARY_NAME}}" build:all: desc: Build binaries for all platforms cmds: - task: build:linux - - task: build:darwin-amd64 + - task: build:linux-arm64 + - task: build:darwin-amd64 - task: build:darwin-arm64 - task: build:windows build:linux: - env: - VERSION: - sh: ./scripts/get-version.sh cmds: - - | - COMMIT=$(git rev-parse --short HEAD) - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION} -w -s" - - mkdir -p {{.BUILD_DIR}} - GOOS=linux GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-amd64 ./{{.SOURCE_DIR}} - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-amd64" + - mkdir -p {{.BUILD_DIR}} + - GOOS=linux GOARCH=amd64 go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-amd64 ./{{.SOURCE_DIR}} + - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-amd64" + + build:linux-arm64: + cmds: + - mkdir -p {{.BUILD_DIR}} + - GOOS=linux GOARCH=arm64 go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-arm64 ./{{.SOURCE_DIR}} + - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-linux-arm64" build:darwin-amd64: - env: - VERSION: - sh: ./scripts/get-version.sh cmds: - - | - COMMIT=$(git rev-parse --short HEAD) - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION} -w -s" - - mkdir -p {{.BUILD_DIR}} - GOOS=darwin GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-amd64 ./{{.SOURCE_DIR}} - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-amd64" + - mkdir -p {{.BUILD_DIR}} + - GOOS=darwin GOARCH=amd64 go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-amd64 ./{{.SOURCE_DIR}} + - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-amd64" build:darwin-arm64: - env: - VERSION: - sh: ./scripts/get-version.sh cmds: - - | - COMMIT=$(git rev-parse --short HEAD) - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION} -w -s" - - mkdir -p {{.BUILD_DIR}} - GOOS=darwin GOARCH=arm64 go build -ldflags="${LDFLAGS}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-arm64 ./{{.SOURCE_DIR}} - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-arm64" + - mkdir -p {{.BUILD_DIR}} + - GOOS=darwin GOARCH=arm64 go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-arm64 ./{{.SOURCE_DIR}} + - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-darwin-arm64" build:windows: - env: - VERSION: - sh: ./scripts/get-version.sh cmds: - - | - COMMIT=$(git rev-parse --short HEAD) - BUILD_TIME=$(date -u +'%Y-%m-%dT%H:%M:%SZ') - GO_VERSION=$(go version | awk '{print $3}') - LDFLAGS="-X main.version=${VERSION} -X main.gitCommit=${COMMIT} -X main.buildTime=${BUILD_TIME} -X main.goVersion=${GO_VERSION} -w -s" - - mkdir -p {{.BUILD_DIR}} - GOOS=windows GOARCH=amd64 go build -ldflags="${LDFLAGS}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-windows-amd64.exe ./{{.SOURCE_DIR}} - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-windows-amd64.exe" - - + - mkdir -p {{.BUILD_DIR}} + - GOOS=windows GOARCH=amd64 go build -ldflags="{{.LDFLAGS}}" -o {{.BUILD_DIR}}/{{.BINARY_NAME}}-windows-amd64.exe ./{{.SOURCE_DIR}} + - echo "✅ {{.BUILD_DIR}}/{{.BINARY_NAME}}-windows-amd64.exe" + + build:dist: + desc: Build all platform release binaries into dist/ with version in filename (used by CI) + cmds: + - mkdir -p {{.DIST_DIR}} + - GOOS=linux GOARCH=amd64 go build -ldflags="{{.LDFLAGS}}" -o {{.DIST_DIR}}/{{.BINARY_NAME}}_{{.VERSION}}_linux_amd64 ./{{.SOURCE_DIR}} + - GOOS=linux GOARCH=arm64 go build -ldflags="{{.LDFLAGS}}" -o {{.DIST_DIR}}/{{.BINARY_NAME}}_{{.VERSION}}_linux_arm64 ./{{.SOURCE_DIR}} + - GOOS=darwin GOARCH=amd64 go build -ldflags="{{.LDFLAGS}}" -o {{.DIST_DIR}}/{{.BINARY_NAME}}_{{.VERSION}}_darwin_amd64 ./{{.SOURCE_DIR}} + - GOOS=darwin GOARCH=arm64 go build -ldflags="{{.LDFLAGS}}" -o {{.DIST_DIR}}/{{.BINARY_NAME}}_{{.VERSION}}_darwin_arm64 ./{{.SOURCE_DIR}} + - GOOS=windows GOARCH=amd64 go build -ldflags="{{.LDFLAGS}}" -o {{.DIST_DIR}}/{{.BINARY_NAME}}_{{.VERSION}}_windows_amd64.exe ./{{.SOURCE_DIR}} + - cd {{.DIST_DIR}} && sha256sum $(ls | grep -v checksums.txt) > checksums.txt + - echo "✅ dist/ ready ({{.VERSION}})" + test: desc: Run tests cmds: - - go test ./... {{.CLI_ARGS}} - + - go test -race ./... {{.CLI_ARGS}} + + test:ci: + desc: Run tests with race detector and coverage (used by CI) + cmds: + - go test -v -race -covermode=atomic -coverprofile=./coverage.out ./... + clean: desc: Clean build artifacts cmds: - go clean - - rm -rf {{.BUILD_DIR}} - - rm -rf {{.MANIFEST_BUILD_DIR}} + - rm -rf {{.BUILD_DIR}} {{.DIST_DIR}} {{.MANIFEST_BUILD_DIR}} - echo "✅ Cleaned" update-golden: desc: Update golden files for tests cmds: - - go test ./... -- -update-golden {{.CLI_ARGS}} + - go test ./... -- -update-golden {{.CLI_ARGS}} doc: desc: Launch pkgsite documentation server cmds: - pkgsite -open - - - - diff --git a/internal/config/testdata/devenv.yaml b/internal/config/testdata/devenv.yaml new file mode 100644 index 0000000..ba6f9fb --- /dev/null +++ b/internal/config/testdata/devenv.yaml @@ -0,0 +1,5 @@ +# Global config fixture for integration tests and CI validation (release.yml). +# Supplies cluster-level defaults that individual developer configs do not define. +image: "ubuntu:22.04" +hostName: "devenv.example.com" +namespace: "devenv"