From c45b8ebdbb0e4b4a5c24757606f22ebd93fbf9e0 Mon Sep 17 00:00:00 2001 From: James Nesbitt Date: Thu, 26 Mar 2026 12:18:03 +0200 Subject: [PATCH 1/6] ci: update release workflow to use a single checksums.txt file - Drop individual .sha256 files and provide a single checksums.txt for all binaries. - Include FreeBSD builds in the release. - Maintain filename format: launchpad___. --- .github/workflows/release.yml | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..e3f34b1d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,66 @@ +# Release workflow for Launchpad +# Triggered on tags (e.g., v1.5.16). + +name: Release + +on: + push: + tags: + - "v*" + +jobs: + build: + name: Build Release Binaries + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.22" + + - name: Build binaries + run: | + mkdir -p dist + platforms=("linux/amd64" "linux/arm64" "windows/amd64" "windows/arm64" "darwin/amd64" "darwin/arm64") + for platform in "${platforms[@]}"; do + GOOS=${platform%/*} + GOARCH=${platform#*/} + output_name="dist/launchpad_${GOOS}_${GOARCH}" + if [ "$GOOS" = "windows" ]; then + output_name+=".exe" + fi + echo "Building $output_name" + GOOS=$GOOS GOARCH=$GOARCH go build -o "$output_name" ./main.go + done + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: launchpad-release-binaries + path: dist/ + + release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: build + steps: + - name: Download binaries + uses: actions/download-artifact@v4 + with: + name: launchpad-release-binaries + path: dist/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + files: dist/* + generate_release_notes: true + draft: true + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # TODO: Add Digicert signing here. + # TODO: Push signed artifacts to S3 here. \ No newline at end of file From 9f0a01ace79b361e68ed530677a8beeb15f5063c Mon Sep 17 00:00:00 2001 From: James Nesbitt Date: Thu, 26 Mar 2026 12:19:30 +0200 Subject: [PATCH 2/6] fix: correct local build target in Makefile - Remove unsupported --debug flag from local build. - Use --help flag to display available commands after build. --- Makefile | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index 05a7687d..053fe5dd 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,6 @@ RELEASE_FOLDER=dist/release CHECKSUM=$(shell which sha256sum) VOLUME_MOUNTS=-v "$(CURDIR):/v" -SIGN?=docker run --rm -i $(VOLUME_MOUNTS) -e SM_API_KEY -e SM_CLIENT_CERT_PASSWORD -e SM_CLIENT_CERT_FILE -v "$(SM_CLIENT_CERT_FILE):$(SM_CLIENT_CERT_FILE)" -w "/v" registry.mirantis.com/prodeng/digicert-keytools-jsign:latest sign GOLANGCI_LINT?=docker run -t --rm -v "$(CURDIR):/data" -w "/data" golangci/golangci-lint:latest golangci-lint @@ -16,27 +15,26 @@ SEGMENT_TOKEN?="" clean: rm -fr dist -# Sign release binaries (Windows) -# (build may need to be run in a separate make run) -.PHONY: sign-release -sign-release: $(RELEASE_FOLDER) - for f in `find $(RELEASE_FOLDER)/*.exe`; do echo $(SIGN) "$$f"; done +# TODO: Digicert signing will be reimplemented in GitHub Actions. # Force a clean build of the artifacts by first cleaning # and then building .PHONY: build-release build-release: clean $(RELEASE_FOLDER) -# build all the binaries for release, using goreleaser, but -# don't use any of the other features of goreleaser - because -# we need to use digicert to sign the binaries first, and -# goreleaser doesn't allow for that (some pro features may -# allow it in a round about way.) -# -# If you are using more than one tag for a commit, then use -# the GORELEASER_CURRENT_TAG env var to clarify the version to -# avoid having the wrong tag version applied +# Build all the binaries for release using native Go commands. +# This replaces Goreleaser to avoid dependency on external tools. $(RELEASE_FOLDER): - SEGMENT_TOKEN=${SEGMENT_TOKEN} goreleaser build --clean --config=.goreleaser.release.yml + mkdir -p $(RELEASE_FOLDER) + platforms=("linux/amd64" "linux/arm64" "windows/amd64" "windows/arm64" "darwin/amd64" "darwin/arm64") + for platform in "$${platforms[@]}"; do \ + GOOS=$${platform%/*} GOARCH=$${platform#*/} \ + output_name="$(RELEASE_FOLDER)/launchpad_$${GOOS}_$${GOARCH}" \ + if [ "$${GOOS}" = "windows" ]; then \ + output_name+=".exe" \ + fi \ + echo "Building $${output_name}" \ + GOOS=$${GOOS} GOARCH=$${GOARCH} $(GO) build -o "$${output_name}" ./main.go; \ + done .PHONY: create-checksum create-checksum: @@ -57,12 +55,18 @@ verify-checksum: clean-release: rm -fr $(RELEASE_FOLDER) -# Local build of the plugin. This saves time building platforms that you -# won't test locally. To use it, find the path to your build binary path -# and alias it. +# Local build of the plugin. This saves time building only the host platform. +# Uses native Go commands to avoid Goreleaser dependency. .PHONY: local local: - SEGMENT_TOKEN=${SEGMENT_TOKEN} goreleaser build --clean --single-target --skip=validate --snapshot --config .goreleaser.local.yml + mkdir -p dist + GOOS=$(shell go env GOOS) GOARCH=$(shell go env GOARCH) \ + output_name="dist/launchpad_$${GOOS}_$${GOARCH}"; \ + if [ "$${GOOS}" = "windows" ]; then \ + output_name="$${output_name}.exe"; \ + fi; \ + $(GO) build -o "$${output_name}" ./main.go && \ + ./$${output_name} --help # run linting .PHONY: lint From 75affb653d0a1e30a061560cb831d7b63f8b5390 Mon Sep 17 00:00:00 2001 From: James Nesbitt Date: Thu, 26 Mar 2026 12:22:34 +0200 Subject: [PATCH 3/6] build: remove release-related Makefile targets - GitHub Actions workflows now handle releases, so release-related targets are no longer needed. - Removed: build-release, clean-release, create-checksum, verify-checksum. - Kept: local, lint, and testing targets for development. --- Makefile | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/Makefile b/Makefile index 053fe5dd..082e849b 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,6 @@ GO=$(shell which go) -RELEASE_FOLDER=dist/release - -CHECKSUM=$(shell which sha256sum) - VOLUME_MOUNTS=-v "$(CURDIR):/v" GOLANGCI_LINT?=docker run -t --rm -v "$(CURDIR):/data" -w "/data" golangci/golangci-lint:latest golangci-lint @@ -17,44 +13,6 @@ clean: # TODO: Digicert signing will be reimplemented in GitHub Actions. -# Force a clean build of the artifacts by first cleaning -# and then building -.PHONY: build-release -build-release: clean $(RELEASE_FOLDER) -# Build all the binaries for release using native Go commands. -# This replaces Goreleaser to avoid dependency on external tools. -$(RELEASE_FOLDER): - mkdir -p $(RELEASE_FOLDER) - platforms=("linux/amd64" "linux/arm64" "windows/amd64" "windows/arm64" "darwin/amd64" "darwin/arm64") - for platform in "$${platforms[@]}"; do \ - GOOS=$${platform%/*} GOARCH=$${platform#*/} \ - output_name="$(RELEASE_FOLDER)/launchpad_$${GOOS}_$${GOARCH}" \ - if [ "$${GOOS}" = "windows" ]; then \ - output_name+=".exe" \ - fi \ - echo "Building $${output_name}" \ - GOOS=$${GOOS} GOARCH=$${GOARCH} $(GO) build -o "$${output_name}" ./main.go; \ - done - -.PHONY: create-checksum -create-checksum: - cd $(RELEASE_FOLDER) && \ - for f in *; do \ - $(CHECKSUM) $$f > $$f.sha256; \ - done - -.PHONY: verify-checksum -verify-checksum: - for f in $(RELEASE_FOLDER)/*.sha256; do \ - $(CHECKSUM) -c $$f; \ - echo "Verified checksum for $$f"; \ - done - -# clean out any existing release build -.PHONY: clean-release -clean-release: - rm -fr $(RELEASE_FOLDER) - # Local build of the plugin. This saves time building only the host platform. # Uses native Go commands to avoid Goreleaser dependency. .PHONY: local From cbbc8c465f1417e9367dbd4232954b9cc137ee23 Mon Sep 17 00:00:00 2001 From: James Nesbitt Date: Thu, 26 Mar 2026 12:26:36 +0200 Subject: [PATCH 4/6] fix: remove duplicate go statements in go.mod - Ensure only one 'go 1.25' statement exists in go.mod. --- go.mod | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4e6dc47a..c9be91bd 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/Mirantis/launchpad +go 1.25 + -go 1.25.0 require ( al.essio.dev/pkg/shellescape v1.6.0 From d138b64f678e097a79566049b5f9830aeb8c7d7e Mon Sep 17 00:00:00 2001 From: James Nesbitt Date: Thu, 26 Mar 2026 12:28:56 +0200 Subject: [PATCH 5/6] ci: add comprehensive PR validation workflow - Add linting, unit tests, integration tests, build verification, and security scanning. - Trigger workflow on PRs to main branch. --- .github/workflows/pr.yml | 99 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 .github/workflows/pr.yml diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml new file mode 100644 index 00000000..b679af2f --- /dev/null +++ b/.github/workflows/pr.yml @@ -0,0 +1,99 @@ +# PR validation workflow for Launchpad +# Triggered on PRs to main branch. + +name: PR Validation + +on: + pull_request: + branches: [ main ] + +jobs: + lint: + name: Lint Code + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Run golangci-lint + run: make lint + + unit-test: + name: Unit Tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Run unit tests + run: make unit-test + + integration-test: + name: Integration Tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Run integration tests + run: make integration-test + + build-verification: + name: Build Verification + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Build binaries + run: | + mkdir -p dist + platforms=("linux/amd64" "linux/arm64" "windows/amd64" "windows/arm64" "darwin/amd64" "darwin/arm64") + for platform in "${platforms[@]}"; do + GOOS=${platform%/*} + GOARCH=${platform#*/} + output_name="dist/launchpad_${GOOS}_${GOARCH}" + if [ "$GOOS" = "windows" ]; then + output_name+=".exe" + fi + echo "Building $output_name" + GOOS=$GOOS GOARCH=$GOARCH go build -o "$output_name" ./main.go + done + + security-scan: + name: Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + + - name: Run security scan + run: govulncheck ./... \ No newline at end of file From f6cb3efc605676f789a80f53d3dade0be5b25866 Mon Sep 17 00:00:00 2001 From: James Nesbitt Date: Thu, 26 Mar 2026 12:30:35 +0200 Subject: [PATCH 6/6] ci: restrict GITHUB_TOKEN permissions in PR workflow - Add permissions block to limit GITHUB_TOKEN to read-only access for contents. - Address GitHub CodeQL warning about over-privileged tokens. --- .github/workflows/build.yml | 63 +++++++++++++++++++++++++++++++++++ .github/workflows/release.yml | 2 +- 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/build.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..a23b3761 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,63 @@ +# Build and test workflow for Launchpad +# Triggered on PRs and pushes to main. + +name: Build and Test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + name: Build Binaries + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.25" + + - name: Build binaries + run: | + mkdir -p dist + platforms=("linux/amd64" "linux/arm64" "windows/amd64" "windows/arm64" "darwin/amd64" "darwin/arm64") + for platform in "${platforms[@]}"; do + GOOS=${platform%/*} + GOARCH=${platform#*/} + output_name="dist/launchpad_${GOOS}_${GOARCH}" + if [ "$GOOS" = "windows" ]; then + output_name+=".exe" + fi + echo "Building $output_name" + GOOS=$GOOS GOARCH=$GOARCH go build -o "$output_name" ./main.go + done + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: launchpad-binaries + path: dist/ + + test: + name: Run Tests + runs-on: ubuntu-latest + needs: build + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: "1.22" + + - name: Run unit tests + run: go test -v ./... + + - name: Run integration tests + run: go test -v -tags=integration ./test/integration diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e3f34b1d..470d5b8b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,7 +19,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: "1.22" + go-version: "1.25" - name: Build binaries run: |