From b64d9755503950db153620773f54550c361f8171 Mon Sep 17 00:00:00 2001 From: Bailey Hayes Date: Tue, 2 Dec 2025 09:48:00 -0500 Subject: [PATCH] fix: publish in dep order Despite passing in a local wit-dir for publishing, wkg requires deps to be published to a registry. This changes the workflow to run sequential jobs in dependency order. a. publish-io, publish-random (no deps, run in parallel) b. publish-clocks (waits for io, random) c. publish-filesystem, publish-sockets (wait for clocks, run in parallel) d. publish-cli (waits for filesystem, sockets) e. publish-http (waits for cli) - publish-io is skipped for prereleases (is_prerelease != 'true') - Other jobs use if: always() && !failure() && !cancelled() to handle skipped io gracefully - validate and create-specification updated to depend on all publish jobs --- .github/workflows/publish-proposal.yml | 82 +++++++++++ .github/workflows/publish.yml | 179 ++++++++++++------------- 2 files changed, 168 insertions(+), 93 deletions(-) create mode 100644 .github/workflows/publish-proposal.yml diff --git a/.github/workflows/publish-proposal.yml b/.github/workflows/publish-proposal.yml new file mode 100644 index 000000000..fd4a815f3 --- /dev/null +++ b/.github/workflows/publish-proposal.yml @@ -0,0 +1,82 @@ +name: Publish Proposal + +# Reusable workflow to publish a single WASI proposal to GHCR + +on: + workflow_call: + inputs: + proposal: + description: 'Name of the proposal to publish' + required: true + type: string + description: + description: 'Description of the proposal' + required: true + type: string + version: + description: 'Version to publish' + required: true + type: string + wit_dir: + description: 'WIT directory (wit or wit-0.3.0-draft)' + required: true + type: string + wkg_version: + description: 'Version of wkg to install' + required: false + type: string + default: '0.13.0' + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write + packages: write + contents: write + attestations: write + + steps: + - name: Checkout repository + uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 + + - name: Install cargo-binstall + uses: cargo-bins/cargo-binstall@3fc81674af4165a753833a94cae9f91d8849049f # v1.16.2 + + - name: Install wkg + shell: bash + run: cargo binstall -y "wkg@${{ inputs.wkg_version }}" + + - name: Login to GitHub Container Registry + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.ORG_PAT }} + + - name: Build WIT package + shell: bash + working-directory: proposals/${{ inputs.proposal }} + run: | + echo "Building ${{ inputs.proposal }} from: $(pwd)" + wkg wit build -o "$GITHUB_WORKSPACE/wasi-${{ inputs.proposal }}.wasm" --wit-dir "${{ inputs.wit_dir }}" + + - name: Publish to GitHub Container Registry + id: publish + uses: bytecodealliance/wkg-github-action@10b3b04b9059ba46208cd7daf7d352af14bded0f # v5 + with: + oci-reference-without-tag: 'ghcr.io/webassembly/wasi/${{ inputs.proposal }}' + file: 'wasi-${{ inputs.proposal }}.wasm' + description: ${{ inputs.description }} + source: 'https://github.com/webassembly/wasi' + homepage: 'https://wasi.dev' + version: ${{ inputs.version }} + licenses: 'Apache-2.0 WITH LLVM-exception' + + - name: Attest build provenance + uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 + with: + subject-name: ghcr.io/webassembly/wasi/${{ inputs.proposal }} + subject-digest: ${{ steps.publish.outputs.digest }} + push-to-registry: true + github-token: ${{ secrets.ORG_PAT }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f448f4757..36117f261 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -68,102 +68,95 @@ jobs: echo "wit_dir=$WIT_DIR" } >> "$GITHUB_OUTPUT" - # Publish each proposal - publish: + # Publish proposals sequentially in dependency order: + # 1. io, random (no WASI dependencies) + # 2. clocks (depends on io) + # 3. filesystem, sockets (depend on io, clocks) + # 4. cli (depends on io, clocks, filesystem, random, sockets) + # 5. http (depends on cli, clocks, io) + + publish-io: needs: setup - runs-on: ubuntu-latest - permissions: - id-token: write - packages: write - contents: write - attestations: write - - strategy: - fail-fast: false - matrix: - proposal: - - name: io - description: "WASI I/O interfaces for streams and poll" - exclude_for_p3: true - - name: random - description: "WASI random number generation interfaces" - - name: clocks - description: "WASI clock interfaces for monotonic and wall clocks" - - name: filesystem - description: "WASI filesystem interfaces" - - name: sockets - description: "WASI socket interfaces for TCP and UDP" - - name: cli - description: "WASI CLI interfaces for command-line programs" - - name: http - description: "WASI HTTP interfaces for HTTP client and server" - - steps: - # Skip proposals marked exclude_for_p3 when publishing prereleases (0.3.0-rc) - - name: Check if should skip - id: skip_check - run: | - if [ "${{ matrix.proposal.exclude_for_p3 }}" == "true" ] && [ "${{ needs.setup.outputs.is_prerelease }}" == "true" ]; then - echo "skip=true" >> "$GITHUB_OUTPUT" - echo "Skipping ${{ matrix.proposal.name }} for P3 prerelease" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - - name: Checkout repository - if: steps.skip_check.outputs.skip != 'true' - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 - - - name: Install cargo-binstall - if: steps.skip_check.outputs.skip != 'true' - uses: cargo-bins/cargo-binstall@3fc81674af4165a753833a94cae9f91d8849049f # v1.16.2 - - - name: Install wkg - if: steps.skip_check.outputs.skip != 'true' - shell: bash - run: cargo binstall -y wkg - - - name: Login to GitHub Container Registry - if: steps.skip_check.outputs.skip != 'true' - uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.ORG_PAT }} - - - name: Build WIT package - if: steps.skip_check.outputs.skip != 'true' - shell: bash - working-directory: proposals/${{ matrix.proposal.name }} - run: | - echo "Building from: $(pwd)" - wkg wit build -o "$GITHUB_WORKSPACE/wasi-${{ matrix.proposal.name }}.wasm" --wit-dir "${{ needs.setup.outputs.wit_dir }}" - - - name: Publish to GitHub Container Registry - if: steps.skip_check.outputs.skip != 'true' - id: publish - uses: bytecodealliance/wkg-github-action@10b3b04b9059ba46208cd7daf7d352af14bded0f # v5 - with: - oci-reference-without-tag: 'ghcr.io/webassembly/wasi/${{ matrix.proposal.name }}' - file: 'wasi-${{ matrix.proposal.name }}.wasm' - description: ${{ matrix.proposal.description }} - source: 'https://github.com/webassembly/wasi' - homepage: 'https://wasi.dev' - version: ${{ needs.setup.outputs.version }} - licenses: 'Apache-2.0 WITH LLVM-exception' - - - name: Attest build provenance - if: steps.skip_check.outputs.skip != 'true' - uses: actions/attest-build-provenance@977bb373ede98d70efdf65b84cb5f73e068dcc2a # v3.0.0 - with: - subject-name: ghcr.io/webassembly/wasi/${{ matrix.proposal.name }} - subject-digest: ${{ steps.publish.outputs.digest }} - push-to-registry: true - github-token: ${{ secrets.ORG_PAT }} + # Skip io for P3 prereleases (no wit-0.3.0-draft directory) + if: needs.setup.outputs.is_prerelease != 'true' + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: io + description: "WASI I/O interfaces for streams and poll" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit + + publish-random: + needs: setup + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: random + description: "WASI random number generation interfaces" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit + + publish-clocks: + needs: [setup, publish-io, publish-random] + # For prereleases, only wait on random (io is skipped) + if: always() && !failure() && !cancelled() + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: clocks + description: "WASI clock interfaces for monotonic and system clocks" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit + + publish-filesystem: + needs: [setup, publish-clocks] + if: always() && !failure() && !cancelled() + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: filesystem + description: "WASI filesystem interfaces" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit + + publish-sockets: + needs: [setup, publish-clocks] + if: always() && !failure() && !cancelled() + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: sockets + description: "WASI socket interfaces for TCP and UDP" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit + + publish-cli: + needs: [setup, publish-filesystem, publish-sockets] + if: always() && !failure() && !cancelled() + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: cli + description: "WASI CLI interfaces for command-line programs" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit + + publish-http: + needs: [setup, publish-cli] + if: always() && !failure() && !cancelled() + uses: ./.github/workflows/publish-proposal.yml + with: + proposal: http + description: "WASI HTTP interfaces for HTTP client and server" + version: ${{ needs.setup.outputs.version }} + wit_dir: ${{ needs.setup.outputs.wit_dir }} + secrets: inherit # Validate all packages were published successfully validate: - needs: [setup, publish] + needs: [setup, publish-io, publish-random, publish-clocks, publish-filesystem, publish-sockets, publish-cli, publish-http] + if: always() && !failure() && !cancelled() runs-on: ubuntu-latest steps: - name: Install oras @@ -205,7 +198,7 @@ jobs: # Create specification entry after all publishes complete create-specification: - needs: [setup, publish, validate] + needs: [setup, validate] runs-on: ubuntu-latest if: needs.setup.outputs.is_prerelease == 'false' permissions: