From a43c4230dd72a71b0a88c914f5f630fed3598296 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 18:11:26 -0700 Subject: [PATCH 1/8] Add setup-vcpkg --- actions/setup-vcpkg/action.yml | 19 +++++ package-lock.json | 20 ++++- package.json | 6 +- src/setup-vcpkg/index.js | 129 +++++++++++++++++++++++++++++++++ 4 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 actions/setup-vcpkg/action.yml create mode 100644 src/setup-vcpkg/index.js diff --git a/actions/setup-vcpkg/action.yml b/actions/setup-vcpkg/action.yml new file mode 100644 index 0000000..0d1c587 --- /dev/null +++ b/actions/setup-vcpkg/action.yml @@ -0,0 +1,19 @@ +name: 'Setup vcpkg' +description: 'Downloads, verifies, extracts, and caches a specific tagged version of vcpkg' +author: 'Your Name/Org' + +inputs: + vcpkg-version: + description: 'The vcpkg tag version to download (e.g., 2025.03.19)' + required: true + vcpkg-hash: + description: 'The expected SHA512 hash of the downloaded zip archive' + required: true + +outputs: + vcpkg-root: + description: 'The installation path of the cached vcpkg instance' + +runs: + using: 'node20' + main: 'dist/index.js' \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index a89200a..ec09e2f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,9 +9,11 @@ "version": "0.0.2", "license": "MIT", "dependencies": { - "@actions/core": "^1.10.1", + "@actions/core": "^1.11.1", "@actions/exec": "^1.1.1", - "@actions/github": "^6.0.0" + "@actions/github": "^6.0.0", + "@actions/io": "^1.1.3", + "@actions/tool-cache": "^2.0.2" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", @@ -75,6 +77,19 @@ "integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==", "license": "MIT" }, + "node_modules/@actions/tool-cache": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@actions/tool-cache/-/tool-cache-2.0.2.tgz", + "integrity": "sha512-fBhNNOWxuoLxztQebpOaWu6WeVmuwa77Z+DxIZ1B+OYvGkGQon6kTVg6Z32Cb13WCuw0szqonK+hh03mJV7Z6w==", + "license": "MIT", + "dependencies": { + "@actions/core": "^1.11.1", + "@actions/exec": "^1.0.0", + "@actions/http-client": "^2.0.1", + "@actions/io": "^1.1.1", + "semver": "^6.1.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -5826,7 +5841,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" diff --git a/package.json b/package.json index 7dd056e..ba70b77 100644 --- a/package.json +++ b/package.json @@ -17,9 +17,11 @@ "author": "", "license": "MIT", "dependencies": { - "@actions/core": "^1.10.1", + "@actions/core": "^1.11.1", "@actions/exec": "^1.1.1", - "@actions/github": "^6.0.0" + "@actions/github": "^6.0.0", + "@actions/io": "^1.1.3", + "@actions/tool-cache": "^2.0.2" }, "devDependencies": { "@eslint/eslintrc": "^3.3.1", diff --git a/src/setup-vcpkg/index.js b/src/setup-vcpkg/index.js new file mode 100644 index 0000000..bc7e81e --- /dev/null +++ b/src/setup-vcpkg/index.js @@ -0,0 +1,129 @@ +const core = require('@actions/core'); +const tc = require('@actions/tool-cache'); +const io = require('@actions/io'); +const exec = require('@actions/exec'); // Import exec +const path = require('path'); +const fs = require('fs'); +const crypto = require('crypto'); + +// Helper function to verify SHA512 hash +async function verifySHA512(filePath, expectedHash) { + return new Promise((resolve, reject) => { + const hash = crypto.createHash('sha512'); + const stream = fs.createReadStream(filePath); + stream.on('error', err => reject(err)); + stream.on('data', chunk => hash.update(chunk)); + stream.on('end', () => { + const actualHash = hash.digest('hex'); + core.info(`Actual SHA512: ${actualHash}`); + core.info(`Expected SHA512: ${expectedHash}`); + resolve(actualHash.toLowerCase() === expectedHash.toLowerCase()); + }); + }); +} + +async function run() { + try { + // --- Get Inputs --- + const vcpkgVersion = core.getInput('vcpkg-version', { required: true }); + const vcpkgHash = core.getInput('vcpkg-hash', { required: true }); + const toolName = 'vcpkg'; + const downloadUrl = `https://github.com/microsoft/vcpkg/archive/refs/tags/${vcpkgVersion}.zip`; + const extractedFolderName = `vcpkg-${vcpkgVersion}`; + + core.info(`Setting up vcpkg version: ${vcpkgVersion}`); + + // --- Cache Check --- + let vcpkgPath = tc.find(toolName, vcpkgVersion); + + if (vcpkgPath) { + core.info(`Found cached vcpkg at: ${vcpkgPath}`); + } else { + core.info(`vcpkg version ${vcpkgVersion} not found in cache. Downloading from ${downloadUrl}`); + + // --- Download --- + const vcpkgZipPath = await tc.downloadTool(downloadUrl); + core.info(`Downloaded vcpkg zip to: ${vcpkgZipPath}`); + + // --- Verify Hash --- + core.info('Verifying SHA512 hash...'); + const hashMatch = await verifySHA512(vcpkgZipPath, vcpkgHash); + if (!hashMatch) { + throw new Error('SHA512 hash verification failed!'); + } + core.info('Hash verification successful.'); + + // --- Extract --- + const tempExtractPath = await tc.extractZip(vcpkgZipPath); + core.info(`Extracted vcpkg to temporary location: ${tempExtractPath}`); + + let extractedPath = path.join(tempExtractPath, extractedFolderName); + if (!fs.existsSync(extractedPath)) { + const files = fs.readdirSync(tempExtractPath); + core.warning(`Expected folder '${extractedFolderName}' not found directly. Contents: ${files.join(', ')}`); + if (files.length === 1 && fs.statSync(path.join(tempExtractPath, files[0])).isDirectory()) { + core.warning(`Assuming first directory '${files[0]}' is the correct one.`); + extractedPath = path.join(tempExtractPath, files[0]); + } else { + throw new Error(`Could not find the extracted vcpkg directory inside ${tempExtractPath}. Expected name pattern: ${extractedFolderName}`); + } + } + + // --- !! NEW: Bootstrap vcpkg !! --- + core.info(`Bootstrapping vcpkg in ${extractedPath}...`); + const bootstrapScriptName = process.platform === 'win32' ? 'bootstrap-vcpkg.bat' : 'bootstrap-vcpkg.sh'; + const bootstrapScriptPath = path.join(extractedPath, bootstrapScriptName); + const bootstrapArgs = ['-disableMetrics']; // Common argument for CI + + // Ensure the script exists before trying to run it + if (!fs.existsSync(bootstrapScriptPath)) { + throw new Error(`Bootstrap script not found at ${bootstrapScriptPath}`); + } + + await core.group('Running vcpkg bootstrap', async () => { + const options = { cwd: extractedPath }; // Execute in the extracted vcpkg directory + + // On non-Windows, make sure the script is executable + if (process.platform !== 'win32') { + await exec.exec('chmod', ['+x', bootstrapScriptPath]); + } + + // Execute the bootstrap script + core.info(`Executing: ${bootstrapScriptPath} ${bootstrapArgs.join(' ')}`); + await exec.exec(bootstrapScriptPath, bootstrapArgs, options); + }); + core.info('vcpkg bootstrapped successfully.'); + // --- !! End Bootstrap Section !! --- + + + // --- Cache Directory (now caches the bootstrapped version) --- + core.info(`Caching bootstrapped directory: ${extractedPath}`); + vcpkgPath = await tc.cacheDir(extractedPath, toolName, vcpkgVersion); + core.info(`Successfully cached vcpkg to: ${vcpkgPath}`); + + // --- Clean up temporary download --- + // await io.rmRF(vcpkgZipPath); // Optional cleanup + // await io.rmRF(tempExtractPath); // Optional cleanup + } + + // --- Set Environment Variable --- + core.info(`Setting VCPKG_INSTALLATION_ROOT to ${vcpkgPath}`); + core.exportVariable('VCPKG_INSTALLATION_ROOT', vcpkgPath); + + // --- Set Output --- + core.setOutput('vcpkg-root', vcpkgPath); + + core.info('vcpkg setup complete.'); + + } catch (error) { + core.setFailed(error.message); + } +} + +// Only call run() automatically if this script is the main entry point +if (require.main === module) { + run(); +} + +// Always export run for testing or other programmatic usage +module.exports = { run }; \ No newline at end of file From 28cfb92a0582f3a6c5a8be3ab5723735b0a5f9ba Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 18:17:24 -0700 Subject: [PATCH 2/8] update --- src/setup-vcpkg/index.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/setup-vcpkg/index.js b/src/setup-vcpkg/index.js index bc7e81e..f5c0092 100644 --- a/src/setup-vcpkg/index.js +++ b/src/setup-vcpkg/index.js @@ -1,6 +1,5 @@ const core = require('@actions/core'); const tc = require('@actions/tool-cache'); -const io = require('@actions/io'); const exec = require('@actions/exec'); // Import exec const path = require('path'); const fs = require('fs'); @@ -69,7 +68,6 @@ async function run() { } } - // --- !! NEW: Bootstrap vcpkg !! --- core.info(`Bootstrapping vcpkg in ${extractedPath}...`); const bootstrapScriptName = process.platform === 'win32' ? 'bootstrap-vcpkg.bat' : 'bootstrap-vcpkg.sh'; const bootstrapScriptPath = path.join(extractedPath, bootstrapScriptName); @@ -100,10 +98,6 @@ async function run() { core.info(`Caching bootstrapped directory: ${extractedPath}`); vcpkgPath = await tc.cacheDir(extractedPath, toolName, vcpkgVersion); core.info(`Successfully cached vcpkg to: ${vcpkgPath}`); - - // --- Clean up temporary download --- - // await io.rmRF(vcpkgZipPath); // Optional cleanup - // await io.rmRF(tempExtractPath); // Optional cleanup } // --- Set Environment Variable --- From c6bbf67c12ac347524f4f4cc0dca06f6e6b84f00 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 18:25:23 -0700 Subject: [PATCH 3/8] update --- README.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1bdbdbf..1baba51 100644 --- a/README.md +++ b/README.md @@ -15,18 +15,25 @@ This project uses `esbuild` to compile the JavaScript source code for each actio ## Available Actions 1. **`build-docker-image`** - * Builds a Docker image, with optional caching and pushing via Azure Container Registry. + * Builds a Docker image, with optional caching and pushing via Azure Container Registry. This Action is Linux only. * See: [`actions/build-docker-image/action.yml`](./actions/build-docker-image/action.yml) - * *(Optional: Add link to a more detailed README if it exists at `actions/build-docker-image/README.md`)* + * See details: [`.github/actions/build-docker-image/README.md`](./.github/actions/build-docker-image/README.md) 2. **`run-build-script-in-docker`** - * Runs the ONNX Runtime `tools/ci_build/build.py` script inside a specified Docker container. + * Runs the ONNX Runtime `tools/ci_build/build.py` script inside a specified Docker container. This Action is Linux only. * Supports different modes (`update`, `build`, `test`). * Includes auto-detection for NVIDIA GPUs (`--gpus all`). * Manages common volume mounts (workspace, cache, test data). * Handles enabling execution providers via `--use_` flags. * See: [`actions/run-build-script-in-docker/action.yml`](./actions/run-build-script-in-docker/action.yml) +3. **`setup-vcpkg`** + * Downloads, verifies, bootstraps, and caches a specific tagged version of vcpkg. This Action is Windows only. + * Sets the `VCPKG_INSTALLATION_ROOT` environment variable for subsequent steps. + * Leverages `@actions/tool-cache` for efficient caching. + * See: [`.github/actions/setup-vcpkg/action.yml`](./.github/actions/setup-vcpkg/action.yml) + * See details: [`.github/actions/setup-vcpkg/README.md`](./.github/actions/setup-vcpkg/README.md) + ## Usage (for Consumers) Because the compiled action code (in the `build/` directory) is not present on the `main` branch or directly associated with version tags in the repository filesystem, you **cannot** use the actions directly like this: From 7a88e511a1c52b33851eaae72f85a8a0cf707fd9 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 18:28:49 -0700 Subject: [PATCH 4/8] Add README --- actions/setup-vcpkg/README.md | 72 +++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 actions/setup-vcpkg/README.md diff --git a/actions/setup-vcpkg/README.md b/actions/setup-vcpkg/README.md new file mode 100644 index 0000000..ab89aef --- /dev/null +++ b/actions/setup-vcpkg/README.md @@ -0,0 +1,72 @@ +# Setup vcpkg GitHub Action + +This action downloads a specific tagged release archive of vcpkg from an internal mirror, verifies its SHA512 hash for integrity, extracts it, runs the necessary vcpkg bootstrap script (`bootstrap-vcpkg.bat` or `bootstrap-vcpkg.sh`), and caches the resulting installation using `@actions/tool-cache`. Currently this action only runs on Windows. + +It simplifies the process of getting a ready-to-use vcpkg instance in your GitHub Actions workflows, ensuring consistency and leveraging caching for speed. + +Once set up, it exports the `VCPKG_INSTALLATION_ROOT` environment variable pointing to the cached installation path, which can be used by subsequent steps (e.g., CMake toolchain configuration). + +## Inputs + +| Input | Description | Required | Example | +| --------------- | ---------------------------------------------------------- | :------: | -------------- | +| `vcpkg-version` | The vcpkg tag version to download (e.g., `2023.10.19`) | `true` | `2025.03.19` | +| `vcpkg-hash` | The expected SHA512 hash of the downloaded `.zip` archive. | `true` | `17e96169...` | + +**Finding Hashes:** You typically need to download the specific tag's zip archive (e.g., `https://github.com/microsoft/vcpkg/archive/refs/tags/YYYY.MM.DD.zip`) and calculate its SHA512 hash locally. + +## Outputs + +| Output | Description | Example Usage | +| ------------ | ---------------------------------------------------- | ------------------------------------------ | +| `vcpkg-root` | The absolute path to the cached vcpkg installation. | `${{ steps.setup_vcpkg.outputs.vcpkg-root }}` | + +## Environment Variables + +This action sets the following environment variable for subsequent steps in the job: + +* **`VCPKG_INSTALLATION_ROOT`**: The absolute path to the cached vcpkg installation directory (same value as the `vcpkg-root` output). This is commonly used by build systems like CMake (`-DCMAKE_TOOLCHAIN_FILE=$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake`). + +## Caching + +* The action utilizes `@actions/tool-cache` for caching. +* The cache key is based on the tool name (`vcpkg`), the specified `vcpkg-version`, and the runner's architecture/OS. +* It caches the **bootstrapped** version of vcpkg, meaning the `vcpkg` executable should be present and ready to use within the cached directory. Subsequent runs hitting the cache will be significantly faster as they skip download, verification, extraction, and bootstrapping. + +## Example Usage + +```yaml +name: Build with vcpkg + +on: [push] + +jobs: + build: + runs-on: windows-latest # Or ubuntu-latest, macos-latest + + steps: + - uses: actions/checkout@v4 + + - name: Setup vcpkg + id: setup_vcpkg # Give it an ID to access outputs + # Assuming the action is in the same repository + uses: ./.github/actions/setup-vcpkg + with: + # Find specific versions and hashes on the vcpkg releases page or repo + vcpkg-version: '2025.03.19' # Replace with desired tag + vcpkg-hash: '17e96169cd3f266c4716fcdc1bb728e6a64f103941ece463a2834d50694eba4fb48f30135503fd466402afa139abc847ef630733c442595d1c34979f261b0114' # Replace with the correct SHA512 hash for the version + + - name: Use vcpkg (CMake Example) + shell: bash # Or pwsh, cmd + run: | + echo "Vcpkg is installed at: $VCPKG_INSTALLATION_ROOT" + echo "Vcpkg root output: ${{ steps.setup_vcpkg.outputs.vcpkg-root }}" + + # Example CMake configuration using the VCPKG_INSTALLATION_ROOT env var + cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=VCPKG\_INSTALLATION\_ROOT/scripts/buildsystems/vcpkg\.cmake +\# Or using the output directly \(less common for env vars\) +\# cmake \-B build \-S \. \-DCMAKE\_TOOLCHAIN\_FILE\={{ steps.setup_vcpkg.outputs.vcpkg-root }}/scripts/buildsystems/vcpkg.cmake + + cmake --build build + +``` \ No newline at end of file From f42ea51fc2c00c44e78d7cdcd642b51a9c74da29 Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 18:30:36 -0700 Subject: [PATCH 5/8] update README --- actions/setup-vcpkg/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/setup-vcpkg/README.md b/actions/setup-vcpkg/README.md index ab89aef..7d8aa13 100644 --- a/actions/setup-vcpkg/README.md +++ b/actions/setup-vcpkg/README.md @@ -4,7 +4,7 @@ This action downloads a specific tagged release archive of vcpkg from an interna It simplifies the process of getting a ready-to-use vcpkg instance in your GitHub Actions workflows, ensuring consistency and leveraging caching for speed. -Once set up, it exports the `VCPKG_INSTALLATION_ROOT` environment variable pointing to the cached installation path, which can be used by subsequent steps (e.g., CMake toolchain configuration). +Once set up, it exports the `VCPKG_INSTALLATION_ROOT` environment variable pointing to the cached installation path, which can be used by subsequent steps (e.g., CMake toolchain configuration). ONNX Runtime's [build.py](https://github.com/microsoft/onnxruntime/blob/main/tools/ci_build/build.py) reads this environment variable. ## Inputs From d544b0d4186da46671c0c816dc5329d4ecb2290a Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 19:19:07 -0700 Subject: [PATCH 6/8] update --- actions/setup-vcpkg/README.md | 9 ++-- package-lock.json | 1 - package.json | 1 - src/setup-vcpkg/index.js | 91 ++++++++++++++++++++++++----------- 4 files changed, 68 insertions(+), 34 deletions(-) diff --git a/actions/setup-vcpkg/README.md b/actions/setup-vcpkg/README.md index 7d8aa13..ebe4929 100644 --- a/actions/setup-vcpkg/README.md +++ b/actions/setup-vcpkg/README.md @@ -8,10 +8,11 @@ Once set up, it exports the `VCPKG_INSTALLATION_ROOT` environment variable point ## Inputs -| Input | Description | Required | Example | -| --------------- | ---------------------------------------------------------- | :------: | -------------- | -| `vcpkg-version` | The vcpkg tag version to download (e.g., `2023.10.19`) | `true` | `2025.03.19` | -| `vcpkg-hash` | The expected SHA512 hash of the downloaded `.zip` archive. | `true` | `17e96169...` | +| Input | Description | Required | Default | Example | +| -------------------- | ---------------------------------------------------------------- | :------: | --------------------------------------------- | -------------- | +| `vcpkg-version` | The vcpkg tag version to download (e.g., `2023.10.19`) | `true` | - | `2025.03.19` | +| `vcpkg-hash` | The expected SHA512 hash (used by Terrapin tool via `-s`). | `true` | - | `17e96169...` | +| `terrapin-tool-path` | Path to the `TerrapinRetrievalTool.exe` executable. | `true` | `C:/local/Terrapin/TerrapinRetrievalTool.exe` | | **Finding Hashes:** You typically need to download the specific tag's zip archive (e.g., `https://github.com/microsoft/vcpkg/archive/refs/tags/YYYY.MM.DD.zip`) and calculate its SHA512 hash locally. diff --git a/package-lock.json b/package-lock.json index ec09e2f..1c4e8cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,7 +12,6 @@ "@actions/core": "^1.11.1", "@actions/exec": "^1.1.1", "@actions/github": "^6.0.0", - "@actions/io": "^1.1.3", "@actions/tool-cache": "^2.0.2" }, "devDependencies": { diff --git a/package.json b/package.json index ba70b77..68376a3 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "@actions/core": "^1.11.1", "@actions/exec": "^1.1.1", "@actions/github": "^6.0.0", - "@actions/io": "^1.1.3", "@actions/tool-cache": "^2.0.2" }, "devDependencies": { diff --git a/src/setup-vcpkg/index.js b/src/setup-vcpkg/index.js index f5c0092..245e8f3 100644 --- a/src/setup-vcpkg/index.js +++ b/src/setup-vcpkg/index.js @@ -1,13 +1,19 @@ const core = require('@actions/core'); const tc = require('@actions/tool-cache'); -const exec = require('@actions/exec'); // Import exec +const exec = require('@actions/exec'); const path = require('path'); -const fs = require('fs'); -const crypto = require('crypto'); - -// Helper function to verify SHA512 hash +const fs = require('fs'); // Needed for verifySHA512 stream +const crypto = require('crypto'); // Needed for verifySHA512 + +/** + * Verifies the SHA512 hash of a downloaded file. + * @param {string} filePath - Path to the file to verify. + * @param {string} expectedHash - The expected SHA512 hash in hex format. + * @returns {Promise} - True if the hash matches, false otherwise. + */ async function verifySHA512(filePath, expectedHash) { return new Promise((resolve, reject) => { + core.info(`Calculating SHA512 for file: ${filePath}`); const hash = crypto.createHash('sha512'); const stream = fs.createReadStream(filePath); stream.on('error', err => reject(err)); @@ -26,11 +32,13 @@ async function run() { // --- Get Inputs --- const vcpkgVersion = core.getInput('vcpkg-version', { required: true }); const vcpkgHash = core.getInput('vcpkg-hash', { required: true }); + const terrapinPath = core.getInput('terrapin-tool-path', { required: true }); + const toolName = 'vcpkg'; - const downloadUrl = `https://github.com/microsoft/vcpkg/archive/refs/tags/${vcpkgVersion}.zip`; const extractedFolderName = `vcpkg-${vcpkgVersion}`; core.info(`Setting up vcpkg version: ${vcpkgVersion}`); + core.info(`Using Terrapin Tool at: ${terrapinPath}`); // --- Cache Check --- let vcpkgPath = tc.find(toolName, vcpkgVersion); @@ -38,21 +46,54 @@ async function run() { if (vcpkgPath) { core.info(`Found cached vcpkg at: ${vcpkgPath}`); } else { - core.info(`vcpkg version ${vcpkgVersion} not found in cache. Downloading from ${downloadUrl}`); + // --- Cache Miss --- + core.info(`vcpkg version ${vcpkgVersion} not found in cache. Downloading via Terrapin Tool...`); + + // --- Determine Download Destination --- + const runnerTempDir = process.env.RUNNER_TEMP; + if (!runnerTempDir) { + throw new Error('RUNNER_TEMP environment variable is not defined.'); + } + const vcpkgZipPath = path.join(runnerTempDir, 'vcpkg.zip'); + core.info(`Terrapin will download to: ${vcpkgZipPath}`); + + // --- Execute Terrapin Download --- + // Note: Terrapin might *also* verify the hash via -s argument. + const terrapinBaseUrl = 'https://vcpkg.storage.devpackages.microsoft.io/artifacts/'; + const terrapinPackageUrl = `https://github.com/microsoft/vcpkg/archive/refs/tags/${vcpkgVersion}.zip`; + const terrapinArgs = [ + '-b', terrapinBaseUrl, + '-a', 'true', + '-u', 'Environment', + '-p', terrapinPackageUrl, + '-s', vcpkgHash, // Hash for verification by Terrapin + '-d', vcpkgZipPath + ]; + + await core.group('Downloading vcpkg via Terrapin Tool', async () => { + await exec.exec(`"${terrapinPath}"`, terrapinArgs); + }); + core.info(`Download via Terrapin completed.`); - // --- Download --- - const vcpkgZipPath = await tc.downloadTool(downloadUrl); - core.info(`Downloaded vcpkg zip to: ${vcpkgZipPath}`); + // --- Verify Download Happened --- + if (!fs.existsSync(vcpkgZipPath)) { + throw new Error(`Download failed: Expected file not found at ${vcpkgZipPath} after Terrapin execution.`); + } - // --- Verify Hash --- - core.info('Verifying SHA512 hash...'); + // --- Verify SHA512 Hash (Manual Check) --- + core.info('Verifying SHA512 hash (manual check)...'); const hashMatch = await verifySHA512(vcpkgZipPath, vcpkgHash); if (!hashMatch) { - throw new Error('SHA512 hash verification failed!'); + // Use core.setFailed for clear failure indication in GitHub Actions UI + core.setFailed('SHA512 hash verification failed! Downloaded file hash does not match expected hash.'); + return; // Stop execution if hash fails } - core.info('Hash verification successful.'); + core.info('Manual hash verification successful.'); + // --- End Manual Hash Check --- + // --- Extract --- + core.info(`Extracting ${vcpkgZipPath}...`); const tempExtractPath = await tc.extractZip(vcpkgZipPath); core.info(`Extracted vcpkg to temporary location: ${tempExtractPath}`); @@ -68,53 +109,47 @@ async function run() { } } + // --- Bootstrap vcpkg --- core.info(`Bootstrapping vcpkg in ${extractedPath}...`); const bootstrapScriptName = process.platform === 'win32' ? 'bootstrap-vcpkg.bat' : 'bootstrap-vcpkg.sh'; const bootstrapScriptPath = path.join(extractedPath, bootstrapScriptName); - const bootstrapArgs = ['-disableMetrics']; // Common argument for CI + const bootstrapArgs = ['-disableMetrics']; - // Ensure the script exists before trying to run it if (!fs.existsSync(bootstrapScriptPath)) { throw new Error(`Bootstrap script not found at ${bootstrapScriptPath}`); } await core.group('Running vcpkg bootstrap', async () => { - const options = { cwd: extractedPath }; // Execute in the extracted vcpkg directory - - // On non-Windows, make sure the script is executable + const options = { cwd: extractedPath }; if (process.platform !== 'win32') { await exec.exec('chmod', ['+x', bootstrapScriptPath]); } - - // Execute the bootstrap script core.info(`Executing: ${bootstrapScriptPath} ${bootstrapArgs.join(' ')}`); await exec.exec(bootstrapScriptPath, bootstrapArgs, options); }); core.info('vcpkg bootstrapped successfully.'); - // --- !! End Bootstrap Section !! --- - - // --- Cache Directory (now caches the bootstrapped version) --- + // --- Cache Directory --- core.info(`Caching bootstrapped directory: ${extractedPath}`); vcpkgPath = await tc.cacheDir(extractedPath, toolName, vcpkgVersion); core.info(`Successfully cached vcpkg to: ${vcpkgPath}`); } - // --- Set Environment Variable --- + // --- Set Environment Variable & Output --- core.info(`Setting VCPKG_INSTALLATION_ROOT to ${vcpkgPath}`); core.exportVariable('VCPKG_INSTALLATION_ROOT', vcpkgPath); - - // --- Set Output --- core.setOutput('vcpkg-root', vcpkgPath); core.info('vcpkg setup complete.'); } catch (error) { + // Catch errors from exec, hash check failure (via setFailed), etc. + // If core.setFailed was already called, this will likely just reiterate. + // If an exception was thrown (e.g., download failed, file not found), this catches it. core.setFailed(error.message); } } -// Only call run() automatically if this script is the main entry point if (require.main === module) { run(); } From bb98f51ea022c3ffce8b3d2e4430d9d3a7f5fb5e Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 19:46:26 -0700 Subject: [PATCH 7/8] update --- actions/setup-vcpkg/action.yml | 9 ++++++--- src/setup-vcpkg/index.js | 8 ++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/actions/setup-vcpkg/action.yml b/actions/setup-vcpkg/action.yml index 0d1c587..8a30977 100644 --- a/actions/setup-vcpkg/action.yml +++ b/actions/setup-vcpkg/action.yml @@ -1,14 +1,17 @@ name: 'Setup vcpkg' description: 'Downloads, verifies, extracts, and caches a specific tagged version of vcpkg' -author: 'Your Name/Org' inputs: vcpkg-version: description: 'The vcpkg tag version to download (e.g., 2025.03.19)' required: true vcpkg-hash: - description: 'The expected SHA512 hash of the downloaded zip archive' - required: true + description: 'The expected SHA512 hash (used by Terrapin tool via -s)' + required: true + terrapin-tool-path: + description: 'Path to the TerrapinRetrievalTool.exe executable' + required: false + default: 'C:/local/Terrapin/TerrapinRetrievalTool.exe' outputs: vcpkg-root: diff --git a/src/setup-vcpkg/index.js b/src/setup-vcpkg/index.js index 245e8f3..9d1d899 100644 --- a/src/setup-vcpkg/index.js +++ b/src/setup-vcpkg/index.js @@ -1,9 +1,9 @@ const core = require('@actions/core'); const tc = require('@actions/tool-cache'); const exec = require('@actions/exec'); -const path = require('path'); -const fs = require('fs'); // Needed for verifySHA512 stream -const crypto = require('crypto'); // Needed for verifySHA512 +const crypto = require('node:crypto'); +const path = require('node:path'); +const fs = require('node:fs'); /** * Verifies the SHA512 hash of a downloaded file. @@ -32,7 +32,7 @@ async function run() { // --- Get Inputs --- const vcpkgVersion = core.getInput('vcpkg-version', { required: true }); const vcpkgHash = core.getInput('vcpkg-hash', { required: true }); - const terrapinPath = core.getInput('terrapin-tool-path', { required: true }); + const terrapinPath = core.getInput('terrapin-tool-path'); const toolName = 'vcpkg'; const extractedFolderName = `vcpkg-${vcpkgVersion}`; From 780d4655388fdb7f43fe6ab8cae58bf15d52081f Mon Sep 17 00:00:00 2001 From: Changming Sun Date: Thu, 27 Mar 2025 19:49:14 -0700 Subject: [PATCH 8/8] update --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1baba51..ff7e3da 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This project uses `esbuild` to compile the JavaScript source code for each actio 1. **`build-docker-image`** * Builds a Docker image, with optional caching and pushing via Azure Container Registry. This Action is Linux only. * See: [`actions/build-docker-image/action.yml`](./actions/build-docker-image/action.yml) - * See details: [`.github/actions/build-docker-image/README.md`](./.github/actions/build-docker-image/README.md) + * See details: [`.github/actions/build-docker-image/README.md`](./.github/actions/build-docker-image/README.md) 2. **`run-build-script-in-docker`** * Runs the ONNX Runtime `tools/ci_build/build.py` script inside a specified Docker container. This Action is Linux only.