v0.2.2 #11
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json | |
| name: Publish | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Version to publish (e.g., 0.1.0)" | |
| required: true | |
| type: string | |
| # Workflow-level permissions use least privilege (read-only). | |
| # Jobs that need elevated permissions (npm OIDC, GHCR push) declare them | |
| # individually on the job — see publish-npm and publish-docker. | |
| permissions: | |
| contents: read | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| # Build native addons on each platform and upload as artifacts. | |
| # These are combined in the publish-npm job to create a cross-platform package. | |
| # | |
| # gnu and win32 builds run tests natively on their platform. | |
| # musl is cross-compiled from the glibc runner (can't run tests on glibc host). | |
| build-native: | |
| name: Build (${{ matrix.build }}) | |
| strategy: | |
| fail-fast: true | |
| matrix: | |
| build: [linux-kvm, linux-musl, windows-whp] | |
| include: | |
| - build: linux-kvm | |
| hypervisor: kvm | |
| run_tests: true | |
| - build: linux-musl | |
| hypervisor: kvm | |
| run_tests: false # musl .node can't run on glibc host | |
| - build: windows-whp | |
| hypervisor: whp | |
| run_tests: true | |
| runs-on: ${{ fromJson( | |
| format('["self-hosted", "{0}", "X64", "1ES.Pool=hld-{1}-amd", "JobId={2}-{3}-{4}-{5}"]', | |
| matrix.hypervisor == 'whp' && 'Windows' || 'Linux', | |
| matrix.hypervisor == 'whp' && 'win2025' || 'kvm', | |
| matrix.build, | |
| github.run_id, | |
| github.run_number, | |
| github.run_attempt)) }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| - uses: hyperlight-dev/ci-setup-workflow@v1.9.0 | |
| with: | |
| rust-toolchain: "1.89" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup | |
| run: just setup | |
| - name: Install musl tools and rebuild for musl target | |
| if: matrix.build == 'linux-musl' | |
| run: | | |
| sudo apt-get update && sudo apt-get install -y musl-tools | |
| rustup target add x86_64-unknown-linux-musl | |
| # Rebuild hyperlight-js NAPI addon targeting musl | |
| hl_dir=$(just resolve-hyperlight-dir) | |
| cd "${hl_dir}/src/js-host-api" | |
| npx napi build --platform --target x86_64-unknown-linux-musl | |
| # Rebuild hyperlight-analysis NAPI addon targeting musl | |
| cd "$GITHUB_WORKSPACE/src/code-validator/guest" | |
| npx napi build --platform --target x86_64-unknown-linux-musl --manifest-path host/Cargo.toml | |
| node -e "require('fs').readdirSync('host').filter(f=>f.endsWith('.node')).forEach(f=>require('fs').copyFileSync('host/'+f,f))" | |
| # Verify musl .node files were actually produced | |
| ls -la "${hl_dir}/src/js-host-api/"*.linux-x64-musl.node | |
| ls -la "$GITHUB_WORKSPACE/src/code-validator/guest/"*linux-x64-musl* || ls -la "$GITHUB_WORKSPACE/src/code-validator/guest/host/"*linux-x64-musl* | |
| - name: Build release binary | |
| if: matrix.run_tests | |
| run: node scripts/build-binary.js --release | |
| env: | |
| VERSION: ${{ github.event.release.tag_name || inputs.version }} | |
| - name: Run tests | |
| if: matrix.run_tests | |
| run: just test | |
| # Upload the native .node addons so the publish job can combine them | |
| - name: Upload native addons | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: native-addons-${{ matrix.build }} | |
| path: | | |
| deps/js-host-api/js-host-api.*.node | |
| src/code-validator/guest/host/hyperlight-analysis.*.node | |
| src/code-validator/guest/hyperlight-analysis.*.node | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Assemble the final npm package tarball on a self-hosted Linux runner | |
| # (needs `just setup` for the hyperlight toolchain to build the binary). | |
| # The resulting tarball is uploaded as an artifact, then published from a | |
| # github-hosted runner — npm sigstore provenance *requires* github-hosted. | |
| pack-npm: | |
| name: Pack npm tarball | |
| needs: [build-native] | |
| permissions: | |
| contents: read | |
| runs-on: [self-hosted, Linux, X64, "1ES.Pool=hld-kvm-amd","JobId=hyperagent-pack-npm-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}"] | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| - uses: hyperlight-dev/ci-setup-workflow@v1.9.0 | |
| with: | |
| rust-toolchain: "1.89" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup | |
| run: just setup | |
| # Download AFTER setup so artifacts land in the symlink/junction target | |
| # that build-hyperlight creates (deps/js-host-api → Cargo checkout). | |
| # Downloading before setup would be clobbered when setup re-creates the link. | |
| - name: Download all native addons | |
| uses: actions/download-artifact@v8 | |
| with: | |
| pattern: native-addons-* | |
| merge-multiple: true | |
| - name: Build binary (with all platform addons present) | |
| run: VERSION="${{ github.event.release.tag_name || inputs.version }}" node scripts/build-binary.js --release | |
| - name: Set version from release tag | |
| if: github.event_name == 'release' | |
| run: npm version ${{ github.event.release.tag_name }} --no-git-tag-version --allow-same-version | |
| - name: Set version from input | |
| if: github.event_name == 'workflow_dispatch' | |
| run: npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version | |
| - name: Pack npm tarball | |
| run: npm pack | |
| - name: Upload npm tarball | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: npm-tarball | |
| path: "*.tgz" | |
| if-no-files-found: error | |
| retention-days: 1 | |
| # Publish the prebuilt tarball from a github-hosted runner. | |
| # npm sigstore provenance (--provenance) only accepts github-hosted runners; | |
| # self-hosted is rejected with: | |
| # E422 Unsupported GitHub Actions runner environment: "self-hosted" | |
| # This job does no building — it just takes the tarball and pushes it. | |
| publish-npm: | |
| name: Publish to npmjs.org | |
| needs: [pack-npm] | |
| # id-token: write is required for npm OIDC trusted publishing. | |
| # Scoped to this job only (least privilege). | |
| permissions: | |
| id-token: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| registry-url: "https://registry.npmjs.org" | |
| # Trusted publishing requires npm >=11.5.1 for OIDC token exchange. | |
| # Pin to ^11.5.1 so we don't silently get an older 11.x that lacks OIDC. | |
| - name: Upgrade npm for trusted publishing | |
| run: npm install -g npm@^11.5.1 && npm --version | |
| - name: Download npm tarball | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: npm-tarball | |
| # OIDC trusted publishing for release events; NPM_TOKEN fallback for workflow_dispatch | |
| - name: Set publish flags | |
| id: publish-flags | |
| run: | | |
| if [ "${{ github.event_name }}" != "workflow_dispatch" ]; then | |
| echo "provenance=--provenance" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "provenance=" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Publish to npmjs.org | |
| run: npm publish *.tgz --access public ${{ steps.publish-flags.outputs.provenance }} | |
| env: | |
| NODE_AUTH_TOKEN: ${{ github.event_name == 'workflow_dispatch' && secrets.NPM_TOKEN || '' }} | |
| # Build and publish Docker image (after tests pass) | |
| publish-docker: | |
| name: Publish to GitHub Container Registry | |
| needs: [build-native] | |
| # packages: write for pushing the image to GHCR. | |
| # Scoped to this job only (least privilege). | |
| permissions: | |
| contents: read | |
| packages: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version: "22" | |
| - uses: hyperlight-dev/ci-setup-workflow@v1.9.0 | |
| with: | |
| rust-toolchain: "1.89" | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Setup | |
| run: just setup | |
| - name: Resolve symlinks for Docker context | |
| run: | | |
| if [ -L deps/js-host-api ]; then | |
| target=$(readlink -f deps/js-host-api) | |
| rm deps/js-host-api | |
| cp -r "$target" deps/js-host-api | |
| fi | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Log in to GitHub Container Registry | |
| uses: docker/login-action@v4 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata for Docker | |
| id: meta | |
| uses: docker/metadata-action@v6 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=semver,pattern={{major}} | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: . | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| build-args: | | |
| VERSION=${{ github.event.release.tag_name || inputs.version }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |