diff --git a/.github/workflows/binary-build.yml b/.github/workflows/binary-build.yml new file mode 100644 index 0000000000..625ecc852f --- /dev/null +++ b/.github/workflows/binary-build.yml @@ -0,0 +1,162 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Build binary and container for single arch + +permissions: + contents: read + +on: + workflow_call: + inputs: + publishType: + required: true + type: string + arch: + required: true + type: string + +env: + EXPECTED_GO_VERSION: "1.24.1" + +jobs: + build: + name: go build and validate + runs-on: ${{ inputs.arch == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }} + permissions: + contents: read + steps: + - name: checkout + uses: actions/checkout@v4 + with: + path: repo + + - name: setup go 1.x + uses: actions/setup-go@v5 + with: + go-version: "${{ env.EXPECTED_GO_VERSION }}" + id: go + + - name: check active go version + run: | + go version && which go + + - name: check go.mod + run: | + set -x + + if grep -q "go $EXPECTED_GO_VERSION" ./repo/toolkit/tools/go.mod; then + echo "go.mod has correct version ($EXPECTED_GO_VERSION)" + else + actual_version="$(grep -E '^go [0-9]+\.[0-9]+' ./repo/toolkit/tools/go.mod)" + echo "go.mod has bad version expected:$EXPECTED_GO_VERSION, found: $actual_version" + echo "UPDATE ./github/workflows/go-test-coverage.yml AND prerequisite documentation if minimum go version changed" + exit 1 + fi + + - name: Check for bad go formatting + run: | + set -x + + pushd repo/toolkit + sudo env "PATH=$PATH" make go-fmt-all + changes=$(git diff *.go) + if [ -n "$changes" ]; then + echo Unformatted go files! + git diff *.go + exit 1 + fi + + - name: check for out-of-date go modules + run: | + set -x + + pushd repo/toolkit + sudo env "PATH=$PATH" make go-mod-tidy + modchanges=$(git diff tools/go.mod) + sumchanges=$(git diff tools/go.sum) + if [ -n "$modchanges$sumchanges" ]; then + echo Module files out of date! + git diff tools/go.mod + git diff tools/go.sum + exit 1 + fi + + - name: check schema.json is up-to-date + run: | + set -x + + pushd repo + make -C toolkit/tools/imagecustomizerschemacli/ + + # Use git diff to check if the schema has changed + schema_changes=$(git diff toolkit/tools/imagecustomizerapi/schema.json) + if [ -n "$schema_changes" ]; then + echo "Schema has changed. Please update the schema using `make -C toolkit/tools/imagecustomizerschemacli/` before committing." + exit 1 + else + echo "Schema is up-to-date!" + fi + + - name: Build binary + run: | + set -x + + # Create version suffix. + case "${{ inputs.publishType }}" in + "official") + PRERELEASE_PARAM="IMAGE_CUSTOMIZER_VERSION_PREVIEW=" + ;; + "preview") + PRERELEASE_PARAM="IMAGE_CUSTOMIZER_VERSION_PREVIEW=-preview.${{github.run_id}}" + ;; + "main") + PRERELEASE_PARAM="IMAGE_CUSTOMIZER_VERSION_PREVIEW=-main.${{github.run_id}}" + ;; + *) + PRERELEASE_PARAM="IMAGE_CUSTOMIZER_VERSION_PREVIEW=-dev.${{github.run_id}}" + ;; + esac + + pushd repo/toolkit + + # Build binary. + sudo env "PATH=$PATH" make imagecustomizer-targz go-imager go-osmodifier $PRERELEASE_PARAM + + # Write version to file. + PACKAGE_VERSION="$(make --silent printvar-image_customizer_full_version $PRERELEASE_PARAM)" + + popd + + echo "$PACKAGE_VERSION" > "version.txt" + + # Print version. + echo "Version: $PACKAGE_VERSION" + + - name: Build container + run: | + set -x + + CONTAINER_TAG="imagecustomizer:build" + ./repo/toolkit/tools/imagecustomizer/container/build-container.sh -t "$CONTAINER_TAG" -a "${{ inputs.arch }}" + + docker image save "$CONTAINER_TAG" | gzip > "imagecustomizer.tar.gz" + + - name: Upload version artifact + if: inputs.arch == 'amd64' + uses: actions/upload-artifact@v4 + with: + name: version + path: version.txt + + - name: Upload binary artifact + uses: actions/upload-artifact@v4 + with: + name: binary-${{ inputs.arch }} + path: repo/toolkit/out/imagecustomizer.tar.gz + + - name: Upload container artifact + uses: actions/upload-artifact@v4 + with: + name: container-${{ inputs.arch }} + path: imagecustomizer.tar.gz diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml deleted file mode 100644 index 3bb0940b37..0000000000 --- a/.github/workflows/build-and-test.yml +++ /dev/null @@ -1,95 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -name: build & test - -permissions: - contents: read - -on: - push: - branches: [main, release/*] - pull_request: - branches: [main, release/*] - workflow_dispatch: {} - -env: - EXPECTED_GO_VERSION: "1.24.1" - -jobs: - build: - name: go build and validate - runs-on: ubuntu-latest - steps: - - name: checkout - uses: actions/checkout@v4 - - - name: setup go 1.x - uses: actions/setup-go@v5 - with: - go-version: "${{ env.EXPECTED_GO_VERSION }}" - id: go - - - name: check active go version - run: | - go version && which go - - - name: check go.mod - run: | - if grep -q "go $EXPECTED_GO_VERSION" ./toolkit/tools/go.mod; then - echo "go.mod has correct version ($EXPECTED_GO_VERSION)" - else - actual_version="$(grep -E '^go [0-9]+\.[0-9]+' ./toolkit/tools/go.mod)" - echo "go.mod has bad version expected:$EXPECTED_GO_VERSION, found: $actual_version" - echo "UPDATE ./github/workflows/go-test-coverage.yml AND prerequisite documentation if minimum go version changed" - exit 1 - fi - - - name: Check for bad go formatting - run: | - pushd toolkit - sudo env "PATH=$PATH" make go-fmt-all - changes=$(git diff *.go) - if [ -n "$changes" ]; then - echo Unformatted go files! - git diff *.go - exit 1 - fi - - - name: check for out-of-date go modules - run: | - pushd toolkit - sudo env "PATH=$PATH" make go-mod-tidy - modchanges=$(git diff tools/go.mod) - sumchanges=$(git diff tools/go.sum) - if [ -n "$modchanges$sumchanges" ]; then - echo Module files out of date! - git diff tools/go.mod - git diff tools/go.sum - exit 1 - fi - - - name: build & test - run: | - pushd toolkit - sudo env "PATH=$PATH" make go-imager go-imagecustomizer go-osmodifier - - - name: check schema.json is up-to-date - run: | - make -C toolkit/tools/imagecustomizerschemacli/ - - # Use git diff to check if the schema has changed - schema_changes=$(git diff toolkit/tools/imagecustomizerapi/schema.json) - if [ -n "$schema_changes" ]; then - echo "Schema has changed. Please update the schema using `make -C toolkit/tools/imagecustomizerschemacli/` before committing." - exit 1 - else - echo "Schema is up-to-date!" - fi - - - name: Build docker image - run: | - ./toolkit/tools/imagecustomizer/container/build-container.sh -t test - - build-docs: - uses: ./.github/workflows/docs-build.yml diff --git a/.github/workflows/build-dev.yml b/.github/workflows/build-dev.yml new file mode 100644 index 0000000000..16a6bc5e0d --- /dev/null +++ b/.github/workflows/build-dev.yml @@ -0,0 +1,21 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Build (dev) + +permissions: + contents: read + +on: + pull_request: + branches: + - main + - release/* + # Allow pipeline to be run manually. + workflow_dispatch: {} + +jobs: + build: + uses: ./.github/workflows/build.yml + with: + publishType: dev diff --git a/.github/workflows/build-main.yml b/.github/workflows/build-main.yml new file mode 100644 index 0000000000..129ba1cc71 --- /dev/null +++ b/.github/workflows/build-main.yml @@ -0,0 +1,18 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Build (main) + +permissions: + contents: read + +on: + push: + branches: + - main + +jobs: + build: + uses: ./.github/workflows/build.yml + with: + publishType: main diff --git a/.github/workflows/build-preview.yml b/.github/workflows/build-preview.yml new file mode 100644 index 0000000000..c9c23fbe8e --- /dev/null +++ b/.github/workflows/build-preview.yml @@ -0,0 +1,18 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Build (preview) + +permissions: + contents: read + +on: + push: + branches: + - release/* + +jobs: + build: + uses: ./.github/workflows/build.yml + with: + publishType: preview diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..bdbb5d2894 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,32 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +name: Build binary, container, and docs + +permissions: + contents: read + +on: + workflow_call: + inputs: + publishType: + required: true + type: string + +jobs: + binary-build-amd64: + name: Build AMD64 + uses: ./.github/workflows/binary-build.yml + with: + publishType: ${{ inputs.publishType }} + arch: amd64 + + binary-build-arm64: + name: Build ARM64 + uses: ./.github/workflows/binary-build.yml + with: + publishType: ${{ inputs.publishType }} + arch: arm64 + + build-docs: + uses: ./.github/workflows/docs-build.yml diff --git a/.github/workflows/docs-build.yml b/.github/workflows/docs-build.yml index 7c0b8d53f8..1e3465fa70 100644 --- a/.github/workflows/docs-build.yml +++ b/.github/workflows/docs-build.yml @@ -10,6 +10,8 @@ jobs: build-docs: name: jekyll github pages build runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout uses: actions/checkout@v4 diff --git a/.github/workflows/github-pages-publishing.yml b/.github/workflows/github-pages-publishing.yml index 7746fab327..adbdf63c87 100644 --- a/.github/workflows/github-pages-publishing.yml +++ b/.github/workflows/github-pages-publishing.yml @@ -1,15 +1,15 @@ name: update GitHub pages -on: - push: - branches: ["stable"] - workflow_dispatch: - permissions: contents: read pages: write id-token: write +on: + push: + branches: + - stable + # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. # However, do NOT cancel in-progress runs as we want to allow these in-progress deployments to complete. concurrency: @@ -21,6 +21,9 @@ jobs: uses: ./.github/workflows/docs-build.yml deploy: + permissions: + pages: write + id-token: write environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} diff --git a/toolkit/scripts/tools.mk b/toolkit/scripts/tools.mk index bf94256d55..10d0e86351 100644 --- a/toolkit/scripts/tools.mk +++ b/toolkit/scripts/tools.mk @@ -90,6 +90,14 @@ $(BUILD_DIR)/tools/internal.test_coverage: $(go_internal_files) $(go_imagegen_fi cd $(TOOLS_DIR)/$* && \ go test -ldflags="$(go_ldflags)" -test.short -covermode=atomic -coverprofile=$@ ./... +.PHONY: imagecustomizer-targz +imagecustomizer-targz: go-imagecustomizer license-scan + rm -rf $(BUILD_DIR)/imagecustomizertar || true + mkdir -p $(BUILD_DIR)/imagecustomizertar + cp $(TOOL_BINS_DIR)/imagecustomizer $(BUILD_DIR)/imagecustomizertar + cp -r $(toolkit_root)/out/LICENSES $(BUILD_DIR)/imagecustomizertar + tar -C $(BUILD_DIR)/imagecustomizertar -cz --file $(toolkit_root)/out/imagecustomizer.tar.gz . + # Downloads all the go dependencies without using sudo, so we don't break other go use cases for the user. # We can check if $SUDO_USER is set (the user who invoked sudo), and if so, use that user to run go get via sudo -u. # We allow the command to fail with || echo ..., since we don't want to fail the build if the user has already diff --git a/toolkit/tools/imagecustomizer/container/build-container.sh b/toolkit/tools/imagecustomizer/container/build-container.sh index 2b5c023aac..ab0191f8e6 100755 --- a/toolkit/tools/imagecustomizer/container/build-container.sh +++ b/toolkit/tools/imagecustomizer/container/build-container.sh @@ -89,7 +89,7 @@ cp "$orasUnzipDir/oras" "${stagingBinDir}" # azl doesn't support grub2-pc for arm64, hence remove it from dockerfile if [ "$ARCH" == "arm64" ]; then echo "Removing grub2-pc and systemd-ukify from Dockerfile for arm64" - sed -i 's/\//g' imagecustomizer.Dockerfile + sed -i 's/\//g' "$dockerFile" fi # build the container