From 924d441aeccc3ee5310352809c8b5cf199889ef3 Mon Sep 17 00:00:00 2001 From: James Devine Date: Fri, 6 Mar 2026 23:19:04 +0000 Subject: [PATCH 1/4] feat: distribute ado-aw via GitHub Releases instead of ADO pipeline artifacts Replace DownloadPipelineArtifact@2 tasks (pipeline 2437, project 4x4) in both standalone and 1ES templates with curl downloads from GitHub Releases, verified via SHA256 checksums. The compiler embeds its own CARGO_PKG_VERSION at compile time so generated pipelines always fetch the matching release. Changes: - Add .github/workflows/release.yml (triggered on v* tags) - Update templates/base.yml and templates/1es-base.yml (6 download sites) - Add {{ compiler_version }} marker replacement in both compilers - Add integration test assertions for new download mechanism - Document {{ compiler_version }} marker in AGENTS.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/release.yml | 62 +++++++++++++++++++++++++++ AGENTS.md | 13 +++++- src/compile/onees.rs | 2 + src/compile/standalone.rs | 2 + templates/1es-base.yml | 78 ++++++++++++++++++++------------- templates/base.yml | 81 +++++++++++++++++++++-------------- tests/compiler_tests.rs | 18 ++++++++ 7 files changed, 192 insertions(+), 64 deletions(-) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..851c93b --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,62 @@ +name: Release + +on: + push: + tags: + - "v*" + +env: + CARGO_TERM_COLOR: always + +permissions: + contents: write + +jobs: + build: + name: Build (Linux) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + + - uses: Swatinem/rust-cache@v2 + + - name: Build + run: cargo build --release --verbose + + - name: Run tests + run: cargo test --verbose + + - name: Prepare release assets + run: | + cd target/release + cp ado-aw ado-aw-linux-x64 + sha256sum ado-aw-linux-x64 > ado-aw-linux-x64.sha256 + + - name: Upload build artifacts + uses: actions/upload-artifact@v4 + with: + name: release-linux + path: | + target/release/ado-aw-linux-x64 + target/release/ado-aw-linux-x64.sha256 + + release: + name: Create Release + needs: build + runs-on: ubuntu-latest + steps: + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: release-linux + path: assets + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: | + assets/ado-aw-linux-x64 + assets/ado-aw-linux-x64.sha256 diff --git a/AGENTS.md b/AGENTS.md index d466053..822893d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -573,6 +573,17 @@ Generates environment variable entries for the copilot AWF step when `read-only- If no `read-only-service-connection` is configured, this marker is replaced with an empty string, and ADO access tokens are omitted from the copilot invocation. +## {{ compiler_version }} + +Should be replaced with the version of the `ado-aw` compiler that generated the pipeline (derived from `CARGO_PKG_VERSION` at compile time). This version is used to construct the GitHub Releases download URL for the `ado-aw` binary. + +The generated pipelines download the compiler binary from: +``` +https://github.com/githubnext/ado-aw/releases/download/v{VERSION}/ado-aw-linux-x64 +``` + +A SHA256 checksum file (`ado-aw-linux-x64.sha256`) is also downloaded and verified to ensure binary integrity. This replaces the previous approach of downloading from an internal ADO pipeline artifact. + ### 1ES-Specific Template Markers The following markers are specific to the 1ES target (`target: 1es`) and are not used in standalone pipelines: @@ -944,7 +955,7 @@ mcp-servers: Network isolation is provided by AWF (Agentic Workflow Firewall), which provides L7 (HTTP/HTTPS) egress control using Squid proxy and Docker containers. AWF restricts network access to a whitelist of approved domains. -The AWF binary is downloaded from an internal ADO pipeline (pipeline 2450, branch `ms/main`, artifact `gh-aw-firewall-linux-x64`). Docker is sourced via the `DockerInstaller@0` ADO task. +The `ado-aw` compiler binary is distributed via [GitHub Releases](https://github.com/githubnext/ado-aw/releases) with SHA256 checksum verification. The AWF binary is downloaded from an internal ADO pipeline (pipeline 2450, branch `ms/main`, artifact `gh-aw-firewall-linux-x64`). Docker is sourced via the `DockerInstaller@0` ADO task. ### Default Allowed Domains diff --git a/src/compile/onees.rs b/src/compile/onees.rs index f702de3..01e7693 100644 --- a/src/compile/onees.rs +++ b/src/compile/onees.rs @@ -114,7 +114,9 @@ displayName: "Finalize""#, ); // Replace all template markers + let compiler_version = env!("CARGO_PKG_VERSION"); let replacements: Vec<(&str, &str)> = vec![ + ("{{ compiler_version }}", compiler_version), ("{{ pool }}", &pool), ("{{ schedule }}", &schedule), ("{{ pr_trigger }}", &pr_trigger), diff --git a/src/compile/standalone.rs b/src/compile/standalone.rs index 257179c..275325b 100644 --- a/src/compile/standalone.rs +++ b/src/compile/standalone.rs @@ -120,7 +120,9 @@ impl Compiler for StandaloneCompiler { ); // Replace template markers + let compiler_version = env!("CARGO_PKG_VERSION"); let replacements: Vec<(&str, &str)> = vec![ + ("{{ compiler_version }}", compiler_version), ("{{ pool }}", &pool), ("{{ setup_job }}", &setup_job), ("{{ teardown_job }}", &teardown_job), diff --git a/templates/1es-base.yml b/templates/1es-base.yml index 430370f..2f5539b 100644 --- a/templates/1es-base.yml +++ b/templates/1es-base.yml @@ -54,16 +54,22 @@ extends: {{ prepare_steps }} - - task: DownloadPipelineArtifact@2 - displayName: "Download agentic pipeline compiler" - inputs: - source: "specific" - project: "4x4" - pipeline: 2437 - runVersion: "latestFromBranch" - branchName: "refs/heads/main" - artifact: "agentic-pipeline-compiler-linux-x64" - targetPath: "$(Pipeline.Workspace)/agentic-pipeline-compiler" + - bash: | + COMPILER_VERSION="{{ compiler_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" + DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" + CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum --check ado-aw.sha256 + chmod +x ado-aw + displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" - bash: | AGENTIC_PIPELINES_PATH="$(Pipeline.Workspace)/agentic-pipeline-compiler/ado-aw" @@ -160,16 +166,22 @@ extends: echo "##vso[task.prependpath]$(Agent.TempDirectory)/tools/agency.linux-x64" displayName: Add agency to PATH - - task: DownloadPipelineArtifact@2 - displayName: "Download agentic pipeline compiler" - inputs: - source: "specific" - project: "4x4" - pipeline: 2437 - runVersion: "latestFromBranch" - branchName: "refs/heads/main" - artifact: "agentic-pipeline-compiler-linux-x64" - targetPath: "$(Pipeline.Workspace)/agentic-pipeline-compiler" + - bash: | + COMPILER_VERSION="{{ compiler_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" + DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" + CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum --check ado-aw.sha256 + chmod +x ado-aw + displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" - bash: | mkdir -p {{ working_directory }}/safe_outputs @@ -297,16 +309,22 @@ extends: - download: current artifact: analyzed_outputs - - task: DownloadPipelineArtifact@2 - displayName: "Download agentic pipeline compiler" - inputs: - source: "specific" - project: "4x4" - pipeline: 2437 - runVersion: "latestFromBranch" - branchName: "refs/heads/main" - artifact: "agentic-pipeline-compiler-linux-x64" - targetPath: "$(Pipeline.Workspace)/agentic-pipeline-compiler" + - bash: | + COMPILER_VERSION="{{ compiler_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" + DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" + CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum --check ado-aw.sha256 + chmod +x ado-aw + displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" - bash: | chmod +x $(Pipeline.Workspace)/agentic-pipeline-compiler/ado-aw diff --git a/templates/base.yml b/templates/base.yml index d6fb5ec..e69874a 100644 --- a/templates/base.yml +++ b/templates/base.yml @@ -52,17 +52,22 @@ jobs: copilot -h displayName: "Output copilot version" - - task: DownloadPipelineArtifact@2 - displayName: "Download agentic pipeline compiler" - name: agenticpipelinecompilerdrop - inputs: - source: "specific" - project: "4x4" - pipeline: 2437 - runVersion: "latestFromBranch" - branchName: "refs/heads/main" - artifact: "agentic-pipeline-compiler-linux-x64" - targetPath: "$(Pipeline.Workspace)/agentic-pipeline-compiler" + - bash: | + COMPILER_VERSION="{{ compiler_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" + DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" + CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum --check ado-aw.sha256 + chmod +x ado-aw + displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" - bash: | AGENTIC_PIPELINES_PATH="$(Pipeline.Workspace)/agentic-pipeline-compiler/ado-aw" @@ -302,17 +307,22 @@ jobs: copilot -h displayName: "Output copilot version" - - task: DownloadPipelineArtifact@2 - displayName: "Download agentic pipeline compiler" - name: agenticpipelinecompilerdrop - inputs: - source: "specific" - project: "4x4" - pipeline: 2437 - runVersion: "latestFromBranch" - branchName: "refs/heads/main" - artifact: "agentic-pipeline-compiler-linux-x64" - targetPath: "$(Pipeline.Workspace)/agentic-pipeline-compiler" + - bash: | + COMPILER_VERSION="{{ compiler_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" + DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" + CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum --check ado-aw.sha256 + chmod +x ado-aw + displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" - task: DockerInstaller@0 displayName: "Install Docker" @@ -488,17 +498,22 @@ jobs: - download: current artifact: analyzed_outputs_$(Build.BuildId) - - task: DownloadPipelineArtifact@2 - displayName: "Download agentic pipeline compiler" - name: agenticpipelinecompilerdrop - inputs: - source: "specific" - project: "4x4" - pipeline: 2437 - runVersion: "latestFromBranch" - branchName: "refs/heads/main" - artifact: "agentic-pipeline-compiler-linux-x64" - targetPath: "$(Pipeline.Workspace)/agentic-pipeline-compiler" + - bash: | + COMPILER_VERSION="{{ compiler_version }}" + DOWNLOAD_DIR="$(Pipeline.Workspace)/agentic-pipeline-compiler" + DOWNLOAD_URL="https://github.com/githubnext/ado-aw/releases/download/v${COMPILER_VERSION}/ado-aw-linux-x64" + CHECKSUM_URL="${DOWNLOAD_URL}.sha256" + + mkdir -p "$DOWNLOAD_DIR" + echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + + echo "Verifying checksum..." + cd "$DOWNLOAD_DIR" + sha256sum --check ado-aw.sha256 + chmod +x ado-aw + displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" - bash: | ls -la "$(Pipeline.Workspace)/agentic-pipeline-compiler" diff --git a/tests/compiler_tests.rs b/tests/compiler_tests.rs index d078353..1bbcee0 100644 --- a/tests/compiler_tests.rs +++ b/tests/compiler_tests.rs @@ -107,6 +107,10 @@ fn test_compiled_yaml_structure() { template_content.contains("{{ agency_params }}"), "Template should contain agency_params marker" ); + assert!( + template_content.contains("{{ compiler_version }}"), + "Template should contain compiler_version marker" + ); // Verify template doesn't accidentally use ${{ }} where {{ }} should be used // (The ${{ }} syntax is for Azure DevOps pipeline expressions and should be preserved) @@ -130,6 +134,20 @@ fn test_compiled_yaml_structure() { !template_content.contains("name: AZS-1ES-L-MMS-ubuntu-22.04"), "Template should not contain hardcoded pool name 'AZS-1ES-L-MMS-ubuntu-22.04'" ); + + // Verify that the ado-aw compiler is downloaded from GitHub Releases, not ADO pipeline artifacts + assert!( + !template_content.contains("pipeline: 2437"), + "Template should not reference ADO pipeline 2437 for the compiler" + ); + assert!( + template_content.contains("github.com/githubnext/ado-aw/releases"), + "Template should download the compiler from GitHub Releases" + ); + assert!( + template_content.contains("sha256sum --check"), + "Template should verify checksum of downloaded compiler" + ); } /// Test that the example file is valid and can be parsed From 3182ebc8886d1f53b74839f6b90ab9459735cab2 Mon Sep 17 00:00:00 2001 From: James Devine Date: Fri, 6 Mar 2026 23:22:51 +0000 Subject: [PATCH 2/4] feat: automate releases with release-please MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace manual tag-triggered release with release-please automation: - On push to main, release-please maintains a Release PR with changelog and Cargo.toml version bump (based on conventional commits) - Merging the Release PR creates the git tag and GitHub Release - Build job then compiles the binary and uploads assets to the release Bump logic: fix: → Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/release.yml | 50 ++++++++++++++++------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 851c93b..e47c7a1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,18 +2,33 @@ name: Release on: push: - tags: - - "v*" + branches: + - main env: CARGO_TERM_COLOR: always permissions: contents: write + pull-requests: write jobs: + release-please: + name: Release Please + runs-on: ubuntu-latest + outputs: + release_created: ${{ steps.release.outputs.release_created }} + tag_name: ${{ steps.release.outputs.tag_name }} + steps: + - uses: googleapis/release-please-action@v4 + id: release + with: + release-type: rust + build: name: Build (Linux) + needs: release-please + if: ${{ needs.release-please.outputs.release_created }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -34,29 +49,10 @@ jobs: cp ado-aw ado-aw-linux-x64 sha256sum ado-aw-linux-x64 > ado-aw-linux-x64.sha256 - - name: Upload build artifacts - uses: actions/upload-artifact@v4 - with: - name: release-linux - path: | - target/release/ado-aw-linux-x64 + - name: Upload release assets + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release upload ${{ needs.release-please.outputs.tag_name }} \ + target/release/ado-aw-linux-x64 \ target/release/ado-aw-linux-x64.sha256 - - release: - name: Create Release - needs: build - runs-on: ubuntu-latest - steps: - - name: Download artifacts - uses: actions/download-artifact@v4 - with: - name: release-linux - path: assets - - - name: Create GitHub Release - uses: softprops/action-gh-release@v2 - with: - generate_release_notes: true - files: | - assets/ado-aw-linux-x64 - assets/ado-aw-linux-x64.sha256 From f30b98727579737de509cf75bf6122b9574bb421 Mon Sep 17 00:00:00 2001 From: James Devine Date: Fri, 6 Mar 2026 23:31:43 +0000 Subject: [PATCH 3/4] fix: checksum verification filename mismatch and pin action versions Fix critical bug where sha256sum --check would always fail because the binary was downloaded as 'ado-aw' but the checksum file references 'ado-aw-linux-x64'. Now downloads as 'ado-aw-linux-x64', verifies the checksum, then renames to 'ado-aw'. Fixed in all 6 download blocks across both templates. Also: - Pin GitHub Actions to commit SHAs for supply-chain security - Add set -euo pipefail to release asset preparation step Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/release.yml | 9 +++++---- templates/1es-base.yml | 21 ++++++++++++--------- templates/base.yml | 21 ++++++++++++--------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e47c7a1..9fd506a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: release_created: ${{ steps.release.outputs.release_created }} tag_name: ${{ steps.release.outputs.tag_name }} steps: - - uses: googleapis/release-please-action@v4 + - uses: googleapis/release-please-action@7987652d64b4581673a76e33ad5e98e3dd56571f # v4.1.3 id: release with: release-type: rust @@ -31,11 +31,11 @@ jobs: if: ${{ needs.release-please.outputs.release_created }} runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc97ebc # stable - - uses: Swatinem/rust-cache@v2 + - uses: Swatinem/rust-cache@9d47c6ad4b02e050fd481d890b2ea34778fd09d6 # v2.7.8 - name: Build run: cargo build --release --verbose @@ -45,6 +45,7 @@ jobs: - name: Prepare release assets run: | + set -euo pipefail cd target/release cp ado-aw ado-aw-linux-x64 sha256sum ado-aw-linux-x64 > ado-aw-linux-x64.sha256 diff --git a/templates/1es-base.yml b/templates/1es-base.yml index 2f5539b..2034b7e 100644 --- a/templates/1es-base.yml +++ b/templates/1es-base.yml @@ -62,12 +62,13 @@ extends: mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw.sha256 + sha256sum --check ado-aw-linux-x64.sha256 + mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -174,12 +175,13 @@ extends: mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw.sha256 + sha256sum --check ado-aw-linux-x64.sha256 + mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -317,12 +319,13 @@ extends: mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw.sha256 + sha256sum --check ado-aw-linux-x64.sha256 + mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" diff --git a/templates/base.yml b/templates/base.yml index e69874a..9c287fb 100644 --- a/templates/base.yml +++ b/templates/base.yml @@ -60,12 +60,13 @@ jobs: mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw.sha256 + sha256sum --check ado-aw-linux-x64.sha256 + mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -315,12 +316,13 @@ jobs: mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw.sha256 + sha256sum --check ado-aw-linux-x64.sha256 + mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" @@ -506,12 +508,13 @@ jobs: mkdir -p "$DOWNLOAD_DIR" echo "Downloading ado-aw v${COMPILER_VERSION} from GitHub Releases..." - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw" "$DOWNLOAD_URL" - curl -fsSL -o "$DOWNLOAD_DIR/ado-aw.sha256" "$CHECKSUM_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64" "$DOWNLOAD_URL" + curl -fsSL -o "$DOWNLOAD_DIR/ado-aw-linux-x64.sha256" "$CHECKSUM_URL" echo "Verifying checksum..." cd "$DOWNLOAD_DIR" - sha256sum --check ado-aw.sha256 + sha256sum --check ado-aw-linux-x64.sha256 + mv ado-aw-linux-x64 ado-aw chmod +x ado-aw displayName: "Download agentic pipeline compiler (v{{ compiler_version }})" From d7a8c863a67089fcfeafbf7e00dc88f50e9b5538 Mon Sep 17 00:00:00 2001 From: James Devine Date: Fri, 6 Mar 2026 23:38:26 +0000 Subject: [PATCH 4/4] fix: add --clobber to release upload and test compiled output markers - Add --clobber to gh release upload for idempotent retries - Add integration test that compiles a fixture through the binary and verifies no unreplaced {{ markers }} remain in the output, confirming {{ compiler_version }} is correctly substituted Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/release.yml | 3 +- tests/compiler_tests.rs | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9fd506a..fa46afd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,4 +56,5 @@ jobs: run: | gh release upload ${{ needs.release-please.outputs.tag_name }} \ target/release/ado-aw-linux-x64 \ - target/release/ado-aw-linux-x64.sha256 + target/release/ado-aw-linux-x64.sha256 \ + --clobber diff --git a/tests/compiler_tests.rs b/tests/compiler_tests.rs index 1bbcee0..0743338 100644 --- a/tests/compiler_tests.rs +++ b/tests/compiler_tests.rs @@ -299,3 +299,57 @@ fn test_fixture_complete_agent() { assert!(content.contains("ado: true"), "Should have built-in MCP"); assert!(content.contains("command:"), "Should have custom MCP"); } + +/// Test that compiled output has no unreplaced template markers +#[test] +fn test_compiled_output_no_unreplaced_markers() { + let temp_dir = + std::env::temp_dir().join(format!("agentic-pipeline-markers-{}", std::process::id())); + fs::create_dir_all(&temp_dir).expect("Failed to create temp directory"); + + let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("tests") + .join("fixtures") + .join("minimal-agent.md"); + + let output_path = temp_dir.join("minimal-agent.yml"); + + // Run the compiler binary + let binary_path = PathBuf::from(env!("CARGO_BIN_EXE_ado-aw")); + let output = std::process::Command::new(&binary_path) + .args(["compile", fixture_path.to_str().unwrap(), "-o", output_path.to_str().unwrap()]) + .output() + .expect("Failed to run compiler"); + + assert!( + output.status.success(), + "Compiler should succeed: {}", + String::from_utf8_lossy(&output.stderr) + ); + assert!(output_path.exists(), "Compiled YAML should exist"); + + let compiled = fs::read_to_string(&output_path).expect("Should read compiled YAML"); + + // Verify no unreplaced {{ markers }} remain (excluding ${{ }} which are ADO expressions) + for line in compiled.lines() { + let stripped = line.replace("${{", ""); + assert!( + !stripped.contains("{{ "), + "Compiled output should not contain unreplaced marker: {}", + line.trim() + ); + } + + // Verify the compiler version was correctly substituted + let version = env!("CARGO_PKG_VERSION"); + assert!( + compiled.contains(version), + "Compiled output should contain compiler version {version}" + ); + assert!( + compiled.contains("github.com/githubnext/ado-aw/releases"), + "Compiled output should reference GitHub Releases" + ); + + let _ = fs::remove_dir_all(&temp_dir); +}