From b74280141bd43b76a66d0fadf080b258f4f332fe Mon Sep 17 00:00:00 2001 From: jiaxiao zhou Date: Sun, 17 Nov 2024 06:42:49 +0000 Subject: [PATCH 01/13] .github/workflows: add wasi-demo-app to the publish pipeline Signed-off-by: jiaxiao zhou --- .github/workflows/release.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 589eeb5a6..3b2978a32 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -182,3 +182,29 @@ jobs: env: GH_TOKEN: ${{ github.token }} RELEASE_NAME: ${{ matrix.crate }}/v${{ matrix.version }} + + release-wasi-demo-app: + permissions: + packages: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup build env + run: ./scripts/setup-linux.sh + - name: Install Rust and wasm32-wasi target + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: wasm32-wasi + override: true + - name: Build oci tarballs + run: | + sudo make test-image + sudo make test-image/oci + ls -l dist/ + - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + - uses: oras-project/setup-oras@v1 + - run: | + oras push ghcr.io/containerd/wasi-demo-app:v${{ inputs.version }} dist/img.tar + oras push ghcr.io/containerd/wasi-demo-app-oci:v${{ inputs.version }} dist/img-oci.tar + oras push ghcr.io/containerd/wasi-demo-app-oci-artifact:v${{ inputs.version }} dist/img-oci-artifact.tar From b670e09e3dd16c64b407f2f5b5a7656a00ecc546 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 01:09:41 +0000 Subject: [PATCH 02/13] refactor(workflows): extract wasi-demo-app release job to a dedicated workflow Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/relaese-wasi-demo-app.yml | 42 +++++++++++++++++++++ .github/workflows/release.yml | 25 ------------ 2 files changed, 42 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/relaese-wasi-demo-app.yml diff --git a/.github/workflows/relaese-wasi-demo-app.yml b/.github/workflows/relaese-wasi-demo-app.yml new file mode 100644 index 000000000..ab3c500cd --- /dev/null +++ b/.github/workflows/relaese-wasi-demo-app.yml @@ -0,0 +1,42 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-action.json + +name: Release +run-name: wasi-demo-app@${{ inputs.version }} + +on: + workflow_dispatch: + inputs: + version: + description: "The version of the crate to release. (e.g., 1.2.3)" + type: string + required: true + +env: + CARGO_TERM_COLOR: always + +jobs: + release-wasi-demo-app: + permissions: + packages: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup build env + run: ./scripts/setup-linux.sh + - name: Install Rust and wasm32-wasi target + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: wasm32-wasi + override: true + - name: Build oci tarballs + run: | + sudo make test-image + sudo make test-image/oci + ls -l dist/ + - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + - uses: oras-project/setup-oras@v1 + - run: | + oras push ghcr.io/containerd/wasi-demo-app:v${{ inputs.version }} dist/img.tar + oras push ghcr.io/containerd/wasi-demo-app-oci:v${{ inputs.version }} dist/img-oci.tar + oras push ghcr.io/containerd/wasi-demo-app-oci-artifact:v${{ inputs.version }} dist/img-oci-artifact.tar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3b2978a32..0c16b426c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -183,28 +183,3 @@ jobs: GH_TOKEN: ${{ github.token }} RELEASE_NAME: ${{ matrix.crate }}/v${{ matrix.version }} - release-wasi-demo-app: - permissions: - packages: write - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Setup build env - run: ./scripts/setup-linux.sh - - name: Install Rust and wasm32-wasi target - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: wasm32-wasi - override: true - - name: Build oci tarballs - run: | - sudo make test-image - sudo make test-image/oci - ls -l dist/ - - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - uses: oras-project/setup-oras@v1 - - run: | - oras push ghcr.io/containerd/wasi-demo-app:v${{ inputs.version }} dist/img.tar - oras push ghcr.io/containerd/wasi-demo-app-oci:v${{ inputs.version }} dist/img-oci.tar - oras push ghcr.io/containerd/wasi-demo-app-oci-artifact:v${{ inputs.version }} dist/img-oci-artifact.tar From e5da98e87c55b9e77be508e240d004a3c7c76082 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 01:29:33 +0000 Subject: [PATCH 03/13] feat(workflows): add dry-run option for wasi-demo-app release workflow and * Renamed relaese-wasi-demo-app.yml to release-wasi-demo-app.yml to fix a typo. * Corrected indentation for the dry_run input in the workflow file. Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/relaese-wasi-demo-app.yml | 42 ---------------- .github/workflows/release-wasi-demo-app.yml | 53 +++++++++++++++++++++ 2 files changed, 53 insertions(+), 42 deletions(-) delete mode 100644 .github/workflows/relaese-wasi-demo-app.yml create mode 100644 .github/workflows/release-wasi-demo-app.yml diff --git a/.github/workflows/relaese-wasi-demo-app.yml b/.github/workflows/relaese-wasi-demo-app.yml deleted file mode 100644 index ab3c500cd..000000000 --- a/.github/workflows/relaese-wasi-demo-app.yml +++ /dev/null @@ -1,42 +0,0 @@ -# yaml-language-server: $schema=https://json.schemastore.org/github-action.json - -name: Release -run-name: wasi-demo-app@${{ inputs.version }} - -on: - workflow_dispatch: - inputs: - version: - description: "The version of the crate to release. (e.g., 1.2.3)" - type: string - required: true - -env: - CARGO_TERM_COLOR: always - -jobs: - release-wasi-demo-app: - permissions: - packages: write - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - name: Setup build env - run: ./scripts/setup-linux.sh - - name: Install Rust and wasm32-wasi target - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - target: wasm32-wasi - override: true - - name: Build oci tarballs - run: | - sudo make test-image - sudo make test-image/oci - ls -l dist/ - - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - uses: oras-project/setup-oras@v1 - - run: | - oras push ghcr.io/containerd/wasi-demo-app:v${{ inputs.version }} dist/img.tar - oras push ghcr.io/containerd/wasi-demo-app-oci:v${{ inputs.version }} dist/img-oci.tar - oras push ghcr.io/containerd/wasi-demo-app-oci-artifact:v${{ inputs.version }} dist/img-oci-artifact.tar diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml new file mode 100644 index 000000000..69b091051 --- /dev/null +++ b/.github/workflows/release-wasi-demo-app.yml @@ -0,0 +1,53 @@ +# yaml-language-server: $schema=https://json.schemastore.org/github-action.json + +name: Release wasi-demo-app +run-name: wasi-demo-app@${{ inputs.version }} + +on: + workflow_dispatch: + inputs: + version: + description: "The version of the crate to release. (e.g., 1.2.3)" + type: string + required: true + dry_run: + description: "Run the release without actually releasing bits" + type: boolean + default: true + +env: + CARGO_TERM_COLOR: always + +jobs: + release-wasi-demo-app: + permissions: + packages: write + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup build env + run: ./scripts/setup-linux.sh + - name: Install Rust and wasm32-wasi target + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: wasm32-wasi + override: true + - name: Build oci tarballs + run: | + make test-image + make test-image/oci + ls -l dist/ + - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + - name: Load tarballs to ctr + run: | + sudo ctr image import dist/img.tar + sudo ctr image import dist/img-oci.tar + sudo ctr image import dist/img-oci-artifact.tar + - name: Push images to ghcr.io + if: ${{ inputs.dry_run == false }} + run: | + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} + From a839a042765d4e75831d5307e40eeccf406b8a88 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 02:19:39 +0000 Subject: [PATCH 04/13] refactor(ci): streamline image build and load steps * Replaced individual make commands with make load and make load/oci. * use repository_owner for image push Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index 69b091051..7ecceb9c0 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -35,19 +35,13 @@ jobs: override: true - name: Build oci tarballs run: | - make test-image - make test-image/oci - ls -l dist/ - - run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - - name: Load tarballs to ctr - run: | - sudo ctr image import dist/img.tar - sudo ctr image import dist/img-oci.tar - sudo ctr image import dist/img-oci-artifact.tar + make load + make load/oci + sudo ctr image ls - name: Push images to ghcr.io if: ${{ inputs.dry_run == false }} run: | - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository_owner }}/wasi-demo-app:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository_owner }}/wasi-demo-oci:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository_owner }}/wasi-demo-oci-artifact:${{ inputs.version }} From cf13998031dba06557eccbe3b514c61c32b31671 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 03:00:30 +0000 Subject: [PATCH 05/13] feat(ci): add image tagging before pushing * push both versioned and latest tags for images Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 25 ++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index 7ecceb9c0..77b3d422f 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -7,7 +7,7 @@ on: workflow_dispatch: inputs: version: - description: "The version of the crate to release. (e.g., 1.2.3)" + description: "The version of the image to release. (e.g., 1.2.3)" type: string required: true dry_run: @@ -19,7 +19,7 @@ env: CARGO_TERM_COLOR: always jobs: - release-wasi-demo-app: + release-wasi-demo-app: permissions: packages: write runs-on: ubuntu-latest @@ -38,10 +38,25 @@ jobs: make load make load/oci sudo ctr image ls + - name: Tagging images + run: | + sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-app:latest ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }} + sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ github.repository }}/wasi-demo-app:latest + + sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }} + sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ github.repository }}/wasi-demo-oci:latest + + sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} + sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest + - name: Push images to ghcr.io if: ${{ inputs.dry_run == false }} run: | - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository_owner }}/wasi-demo-app:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository_owner }}/wasi-demo-oci:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository_owner }}/wasi-demo-oci-artifact:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-app:latest + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci:latest + + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} + sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest From dc4f3f4b95d5b7e4c23c1a464ed6099d20d0b3df Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 03:30:39 +0000 Subject: [PATCH 06/13] feat(ci): add SBOM and signing workflows for OCI images * Added a sign.yml workflow to sign container images using cosign. * Added sbom.yml workflow to generate, sign, and attach SBOMs to OCI images. * Added new workflows (sign-wasi-demo-app, sbom-wasi-demo-app, etc.) into the release pipeline for all image types. Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 57 +++++++++++++- .github/workflows/sbom.yml | 87 +++++++++++++++++++++ .github/workflows/sign.yml | 37 +++++++++ 3 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/sbom.yml create mode 100644 .github/workflows/sign.yml diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index 77b3d422f..a4b376817 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -19,7 +19,7 @@ env: CARGO_TERM_COLOR: always jobs: - release-wasi-demo-app: + release-wasi-demo: permissions: packages: write runs-on: ubuntu-latest @@ -49,6 +49,7 @@ jobs: sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest + - name: Push images to ghcr.io if: ${{ inputs.dry_run == false }} run: | @@ -60,3 +61,57 @@ jobs: sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest + + sign-wasi-demo-app: + if: ${{ inputs.dry_run == false }} + needs: + - release-wasi-demo + uses: ./.github/workflows/sign.yml + with: + image-name: "wasi-demo-app" + version: ${{ inputs.version }} + + sbom-wasi-demo-app: + if: ${{ inputs.dry_run == false }} + needs: + - release-wasi-demo + uses: ./.github/workflows/sbom.yml + with: + image-name: "wasi-demo-app" + version: ${{ inputs.version }} + + sign-wasi-demo-oci: + if: ${{ inputs.dry_run == false }} + needs: + - release-wasi-demo + uses: ./.github/workflows/sign.yml + with: + image-name: "wasi-demo-oci" + version: ${{ inputs.version }} + + sbom-wasi-demo-oci: + if: ${{ inputs.dry_run == false }} + needs: + - release-wasi-demo + uses: ./.github/workflows/sbom.yml + with: + image-name: "wasi-demo-oci" + version: ${{ inputs.version }} + + sign-wasi-demo-oci-artifact: + if: ${{ inputs.dry_run == false }} + needs: + - release-wasi-demo + uses: ./.github/workflows/sign.yml + with: + image-name: "wasi-demo-oci-artifact" + version: ${{ inputs.version }} + + sbom-wasi-demo-oci-artifact: + if: ${{ inputs.dry_run == false }} + needs: + - release-wasi-demo + uses: ./.github/workflows/sbom.yml + with: + image-name: "wasi-demo-oci-artifact" + version: ${{ inputs.version }} diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml new file mode 100644 index 000000000..6f094c108 --- /dev/null +++ b/.github/workflows/sbom.yml @@ -0,0 +1,87 @@ +name: Generate SBOMs + +on: + workflow_call: + inputs: + image-name: + type: string + required: true + version: + description: "The version of the image to release. (e.g., 1.2.3)" + type: string + required: true + +jobs: + sbom: + name: Generate SBOM, sign and attach them to OCI image + strategy: + matrix: + arch: [amd64, arm64] + + permissions: + packages: write + id-token: write + + runs-on: ubuntu-latest + steps: + - name: Install cosign + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + + - name: Install syft + uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0 + + - name: Install crane + uses: IAreKyleW00t/crane-installer@66858ae469ebd32ce731051d9c2bae9b811537e9 # v1.3 + + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Find platform digest + shell: bash + run: | + set -e + IMG_REPOSITORY_NAME=$( echo ${{ github.repository_owner }} | awk '{print tolower($0)}' ) + echo IMG_REPOSITORY_NAME=${IMG_REPOSITORY_NAME} >> $GITHUB_ENV + DIGEST=$(crane digest \ + ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.version }}) + echo "PLATFORM_DIGEST=${DIGEST}" >> "$GITHUB_ENV" + + - name: Create SBOM file + shell: bash + run: | + syft \ + -o spdx-json \ + --file ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ env.PLATFORM_DIGEST }} + + - name: Sign SBOM file + run: | + cosign sign-blob --yes \ + --output-certificate ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx.cert \ + --output-signature ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx.sig \ + ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx + + - name: Attach SBOM to container image + shell: bash + run: | + cosign attach \ + sbom --sbom ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ env.PLATFORM_DIGEST }} + + - name: Sign SBOM file pushed to OCI registry + shell: bash + run: | + set -e + SBOM_TAG="$(echo ${{ env.PLATFORM_DIGEST }} | sed -e 's/:/-/g').sbom" + cosign sign --yes \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}:${SBOM_TAG} + + - name: Upload SBOMs as artifacts + uses: actions/upload-artifact@v4 + with: + name: sbom-${{ matrix.arch }} + path: ${{ inputs.image-name }}-sbom-* \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml new file mode 100644 index 000000000..99f022808 --- /dev/null +++ b/.github/workflows/sign.yml @@ -0,0 +1,37 @@ +name: Sign image + +on: + workflow_call: + inputs: + image-name: + type: string + required: true + version: + description: "The version of the image to release. (e.g., 1.2.3)" + type: string + required: true + +jobs: + sign: + name: Sign image + permissions: + packages: write + id-token: write + + runs-on: ubuntu-latest + steps: + - name: Install cosign + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 + + - name: Login to GitHub Container Registry + uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Sign container image + run: | + IMG_REPOSITORY_NAME=$( echo ${{ github.repository_owner }} | awk '{print tolower($0)}' ) + cosign sign --yes \ + ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.version }} \ No newline at end of file From 6d08f42c7de89317cc2827e3daea67a4fb588821 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 03:39:24 +0000 Subject: [PATCH 07/13] fix(ci): correct image reference to use tag instead of digest * use image digests for signing and SBOM generation * Updated sign.yml and sbom.yml to use image-digest instead of version * use github.repository_owner for image references * use github.repository for image reference * use lowercase repository name Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 38 ++++++++++++++++----- .github/workflows/sbom.yml | 9 +++-- .github/workflows/sign.yml | 9 +++-- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index a4b376817..04487e6d3 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -23,6 +23,10 @@ jobs: permissions: packages: write runs-on: ubuntu-latest + outputs: + wasi_demo_app_digest: ${{ steps.get_digests.outputs.wasi_demo_app_digest }} + wasi_demo_oci_digest: ${{ steps.get_digests.outputs.wasi_demo_oci_digest }} + wasi_demo_oci_artifact_digest: ${{ steps.get_digests.outputs.wasi_demo_oci_artifact_digest }} steps: - uses: actions/checkout@v4 - name: Setup build env @@ -48,8 +52,7 @@ jobs: sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest - - + - name: Push images to ghcr.io if: ${{ inputs.dry_run == false }} run: | @@ -62,6 +65,21 @@ jobs: sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest + - name: Display image digests + id: get_digests + run: | + digest_wasi_demo_app=$(sudo ctr images ls | grep "ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }}" | awk '{print $3}') + echo "Digest for wasi-demo-app: $digest_wasi_demo_app" + echo "wasi_demo_app_digest=$digest_wasi_demo_app" >> $GITHUB_OUTPUT + + digest_wasi_demo_oci=$(sudo ctr images ls | grep "ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }}" | awk '{print $3}') + echo "Digest for wasi-demo-oci: $digest_wasi_demo_oci" + echo "wasi_demo_oci_digest=$digest_wasi_demo_oci" >> $GITHUB_OUTPUT + + digest_wasi_demo_oci_artifact=$(sudo ctr images ls | grep "ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }}" | awk '{print $3}') + echo "Digest for wasi-demo-oci-artifact: $digest_wasi_demo_oci_artifact" + echo "wasi_demo_oci_artifact_digest=$digest_wasi_demo_oci_artifact" >> $GITHUB_OUTPUT + sign-wasi-demo-app: if: ${{ inputs.dry_run == false }} needs: @@ -69,7 +87,7 @@ jobs: uses: ./.github/workflows/sign.yml with: image-name: "wasi-demo-app" - version: ${{ inputs.version }} + image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_app_digest }} sbom-wasi-demo-app: if: ${{ inputs.dry_run == false }} @@ -78,7 +96,8 @@ jobs: uses: ./.github/workflows/sbom.yml with: image-name: "wasi-demo-app" - version: ${{ inputs.version }} + image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_app_digest }} + sign-wasi-demo-oci: if: ${{ inputs.dry_run == false }} @@ -87,7 +106,8 @@ jobs: uses: ./.github/workflows/sign.yml with: image-name: "wasi-demo-oci" - version: ${{ inputs.version }} + image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_digest }} + sbom-wasi-demo-oci: if: ${{ inputs.dry_run == false }} @@ -96,7 +116,8 @@ jobs: uses: ./.github/workflows/sbom.yml with: image-name: "wasi-demo-oci" - version: ${{ inputs.version }} + image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_digest }} + sign-wasi-demo-oci-artifact: if: ${{ inputs.dry_run == false }} @@ -105,7 +126,8 @@ jobs: uses: ./.github/workflows/sign.yml with: image-name: "wasi-demo-oci-artifact" - version: ${{ inputs.version }} + image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_artifact_digest }} + sbom-wasi-demo-oci-artifact: if: ${{ inputs.dry_run == false }} @@ -114,4 +136,4 @@ jobs: uses: ./.github/workflows/sbom.yml with: image-name: "wasi-demo-oci-artifact" - version: ${{ inputs.version }} + image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_artifact_digest }} diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml index 6f094c108..4b58da622 100644 --- a/.github/workflows/sbom.yml +++ b/.github/workflows/sbom.yml @@ -6,8 +6,7 @@ on: image-name: type: string required: true - version: - description: "The version of the image to release. (e.g., 1.2.3)" + image-digest: type: string required: true @@ -37,17 +36,17 @@ jobs: uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ github.repository }} password: ${{ secrets.GITHUB_TOKEN }} - name: Find platform digest shell: bash run: | set -e - IMG_REPOSITORY_NAME=$( echo ${{ github.repository_owner }} | awk '{print tolower($0)}' ) + IMG_REPOSITORY_NAME=$( echo ${{ github.repository }} | awk '{print tolower($0)}' ) echo IMG_REPOSITORY_NAME=${IMG_REPOSITORY_NAME} >> $GITHUB_ENV DIGEST=$(crane digest \ - ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.version }}) + ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.image-digest }}) echo "PLATFORM_DIGEST=${DIGEST}" >> "$GITHUB_ENV" - name: Create SBOM file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index 99f022808..6a8c4e882 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -6,8 +6,7 @@ on: image-name: type: string required: true - version: - description: "The version of the image to release. (e.g., 1.2.3)" + image-digest: type: string required: true @@ -27,11 +26,11 @@ jobs: uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ github.repository }} password: ${{ secrets.GITHUB_TOKEN }} - name: Sign container image run: | - IMG_REPOSITORY_NAME=$( echo ${{ github.repository_owner }} | awk '{print tolower($0)}' ) + IMG_REPOSITORY_NAME=$( echo ${{ github.repository }} | awk '{print tolower($0)}' ) cosign sign --yes \ - ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.version }} \ No newline at end of file + ghcr.io/${{ github.repository }}/${{ inputs.image-name }}@${{ inputs.image-digest }} \ No newline at end of file From 0921356e0dd864143b18fe6cd73c7f7bc28eb5e1 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 16 Dec 2024 04:21:05 +0000 Subject: [PATCH 08/13] fix(ci): adjust syft command and repository reference for signing * Removed matrix strategy for architecture in sbom.yml * Remove crane and platform digest * Use wasm32-wasip1 target Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 2 +- .github/workflows/sbom.yml | 33 ++++++++------------- .github/workflows/sign.yml | 4 +-- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index 04487e6d3..ad5409028 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -35,7 +35,7 @@ jobs: uses: actions-rs/toolchain@v1 with: toolchain: stable - target: wasm32-wasi + target: wasm32-wasip1 override: true - name: Build oci tarballs run: | diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml index 4b58da622..d9f0e0ec4 100644 --- a/.github/workflows/sbom.yml +++ b/.github/workflows/sbom.yml @@ -13,10 +13,6 @@ on: jobs: sbom: name: Generate SBOM, sign and attach them to OCI image - strategy: - matrix: - arch: [amd64, arm64] - permissions: packages: write id-token: write @@ -29,9 +25,6 @@ jobs: - name: Install syft uses: anchore/sbom-action/download-syft@e8d2a6937ecead383dfe75190d104edd1f9c5751 # v0.16.0 - - name: Install crane - uses: IAreKyleW00t/crane-installer@66858ae469ebd32ce731051d9c2bae9b811537e9 # v1.3 - - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: @@ -39,48 +32,46 @@ jobs: username: ${{ github.repository }} password: ${{ secrets.GITHUB_TOKEN }} - - name: Find platform digest + - name: Find repository name shell: bash run: | set -e IMG_REPOSITORY_NAME=$( echo ${{ github.repository }} | awk '{print tolower($0)}' ) echo IMG_REPOSITORY_NAME=${IMG_REPOSITORY_NAME} >> $GITHUB_ENV - DIGEST=$(crane digest \ - ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.image-digest }}) - echo "PLATFORM_DIGEST=${DIGEST}" >> "$GITHUB_ENV" - name: Create SBOM file shell: bash run: | - syft \ + SYFT=$(which syft) + sudo $SYFT \ -o spdx-json \ - --file ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx \ - ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ env.PLATFORM_DIGEST }} + --file ${{ inputs.image-name }}-sbom.spdx \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ inputs.image-digest }} - name: Sign SBOM file run: | cosign sign-blob --yes \ - --output-certificate ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx.cert \ - --output-signature ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx.sig \ - ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx + --output-certificate ${{ inputs.image-name }}-sbom.spdx.cert \ + --output-signature ${{ inputs.image-name }}-sbom.spdx.sig \ + ${{ inputs.image-name }}-sbom.spdx - name: Attach SBOM to container image shell: bash run: | cosign attach \ - sbom --sbom ${{ inputs.image-name }}-sbom-${{ matrix.arch }}.spdx \ - ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ env.PLATFORM_DIGEST }} + sbom --sbom ${{ inputs.image-name }}-sbom.spdx \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ inputs.image-digest }} - name: Sign SBOM file pushed to OCI registry shell: bash run: | set -e - SBOM_TAG="$(echo ${{ env.PLATFORM_DIGEST }} | sed -e 's/:/-/g').sbom" + SBOM_TAG="$(echo ${{ inputs.image-digest }} | sed -e 's/:/-/g').sbom" cosign sign --yes \ ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}:${SBOM_TAG} - name: Upload SBOMs as artifacts uses: actions/upload-artifact@v4 with: - name: sbom-${{ matrix.arch }} + name: sbom path: ${{ inputs.image-name }}-sbom-* \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index 6a8c4e882..1efa94da1 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -23,7 +23,7 @@ jobs: uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 - name: Login to GitHub Container Registry - uses: docker/login-action@0d4c9c5ea7693da7b068278f7b52bda2a190a446 # v3.2.0 + uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.repository }} @@ -33,4 +33,4 @@ jobs: run: | IMG_REPOSITORY_NAME=$( echo ${{ github.repository }} | awk '{print tolower($0)}' ) cosign sign --yes \ - ghcr.io/${{ github.repository }}/${{ inputs.image-name }}@${{ inputs.image-digest }} \ No newline at end of file + ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.image-digest }} \ No newline at end of file From fdf78a2d6d2ca84b893d47843871d37854ef4551 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Fri, 17 Jan 2025 03:16:41 +0000 Subject: [PATCH 09/13] docs(RELEASE): update the release document to account for wasi-demo-app release process Signed-off-by: Jiaxiao (mossaka) Zhou --- RELEASE.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index d6085ac58..86232f664 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,8 +1,27 @@ -# Releasing a new crate version +# Release Process -This document describes the steps to release a new version of the crate. +This document describes the steps to release a new version of the crate or wasi-demo-app images. -## Overview +## Table of Contents + +1. [Crate Release Process](#crate-release-process) + - [Overview](#overview) + - [Input Values for Release.yml](#input-values-for-releaseyml) + - [Crate Release Sequence](#crate-release-sequence) + - [Release Steps](#release-steps) + - [Local Development vs. Release](#local-development-vs-release) + - [Verify signing](#verify-signing) + - [First time release of a crate](#first-time-release-of-a-crate) + - [Release workflow summary](#release-workflow-summary) +2. [wasi-demo-app Release Process](#wasi-demo-app-release-process) + - [Overview](#overview-1) + - [Verify signing](#verify-signing-1) + + + +## Crate Release Process + +### Overview To create a new release, either run the release.yml workflow as a workload_dispatch trigger through the GitHub UI, or via the following command substituting the proper values for crate and version. ```bash @@ -20,7 +39,7 @@ Must release the creates in this order due to dependencies: 1. `containerd-shim-wasm` 2. All runtime-related crates. -## Release Steps +### Release Steps 1. Open a PR to bump crate versions and dependency versions in `Cargo.toml` for that crate, and change the "Unreleased" section in the `CHANGELOG.md` to the new version. 2. PR can be merged after 2 LGTMs @@ -33,7 +52,7 @@ Must release the creates in this order due to dependencies: > > For step 5, some crates have binaries, such as the containerd-shim-wasmtime crate. These binaries are built as part of the release workflow and uploaded to the GitHub release page. You can download the binaries from the release page and verify that they work as expected. -## Local Development vs. Release +### Local Development vs. Release Locally, crates reference local paths. During release, they target published versions. Use both `path` and `version` fields in the workspace `Cargo.toml`: @@ -43,7 +62,7 @@ e.g. containerd-shim-wasm = { path = "crates/containerd-shim-wasm", version = "0.4.0" } ``` -## Verify signing +### Verify signing The release pipeline uses `cosign` to sign the release blobs, if any. It uses Github's OIDC token to authenticate with Sigstore to prove identity and outputs a `.bundle` file, which contains a signature and a key. This file can be verified using `cosign verify-blob` command, providing the workflow tag and Github as the issuer. The full command looks like this (e.g. wasmtime shim): @@ -56,7 +75,7 @@ containerd-shim-wasmtime-v1 In the Github release page, please provide the above command in the instructions for the consumer to verify the release. -## First time release of a crate +### First time release of a crate If the crate has never been published to crates.io before then ownership of the crate will need to be configured. The containerd/runwasi-committers team will need to be added as an owner of the crate. @@ -72,7 +91,7 @@ Alternatively, the cargo cli does support setting the token via an environment v Now all members of the containerd/runwasi-committers team will have access to manage the crate (after they have accepted the invite to the crate). -## Release workflow summary +### Release workflow summary The workflow performs the following steps: - Verifies inputs @@ -85,3 +104,25 @@ The workflow performs the following steps: - Creates a GitHub release for that crate (attaching any artifacts) The workflow utilizes a bot account (@containerd-runwasi-release-bot) to publish the crate to crates.io. The bot account is only used to get a limited-scope API token to publish the crate on crates.io. The token is stored as a secret in the repository and is only used by the release workflow. + +## `wasi-demo-app` Release Process + + +### wasi-demo-app Release Sequence + + +### Overview + +To release a new version of the wasi-demo-app images, run the release-wasi-demo-app.yml workflow using the following command, substituting the correct version: + +```bash +gh workflow run release-wasi-demo-app.yml -f dry_run=false -f version=0.1.0 +``` + +### Verify signing + +To verify the signature of the release, run the following command: + +```bash +cosign verify ghcr.io/containerd/runwasi/wasi-demo-app:0.1.0 --certificate-identity https://github.com/containerd/runwasi/.github/workflows/sign.yml@refs/heads/main --certificate-oidc-issuer https://token.actions.githubusercontent.com +``` \ No newline at end of file From 8f8e6cf1678e27422bc8b72c6e2d5656531b102e Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Fri, 24 Jan 2025 00:03:16 +0000 Subject: [PATCH 10/13] fix(ci): use docker instead of ctr to push images to avoid leaking sensitive token Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 57 ++++++++++++++------- Makefile | 10 ++++ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index ad5409028..444a8c7bf 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -37,46 +37,65 @@ jobs: toolchain: stable target: wasm32-wasip1 override: true + + - name: Convert repository name to lowercase + id: prep + run: echo "::set-output name=repo::$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" + + - name: login to GitHub container registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: enable containerd image store + run: | + echo '{ "features": { "containerd-snapshotter": true } }' | sudo tee /etc/docker/daemon.json + sudo systemctl restart docker + docker info -f '{{ .DriverStatus }}' + - name: Build oci tarballs run: | - make load - make load/oci - sudo ctr image ls + make docker/load + make docker/load/oci + docker image ls + - name: Tagging images run: | - sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-app:latest ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }} - sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ github.repository }}/wasi-demo-app:latest + docker tag ghcr.io/containerd/runwasi/wasi-demo-app:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:${{ inputs.version }} + docker tag ghcr.io/containerd/runwasi/wasi-demo-app:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:latest - sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }} - sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ github.repository }}/wasi-demo-oci:latest + docker tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:${{ inputs.version }} + docker tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:latest - sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} - sudo ctr image tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest + docker tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:${{ inputs.version }} + docker tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:latest - name: Push images to ghcr.io if: ${{ inputs.dry_run == false }} run: | - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-app:latest + docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:${{ inputs.version }} + docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:latest + + docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:${{ inputs.version }} + docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:latest - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci:latest - - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }} - sudo ctr images push --user ${{ github.actor }}:${{ secrets.GITHUB_TOKEN }} ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:latest + docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:${{ inputs.version }} + docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:latest - name: Display image digests id: get_digests run: | - digest_wasi_demo_app=$(sudo ctr images ls | grep "ghcr.io/${{ github.repository }}/wasi-demo-app:${{ inputs.version }}" | awk '{print $3}') + digest_wasi_demo_app=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app --format '{{ .Id }}' --type image) echo "Digest for wasi-demo-app: $digest_wasi_demo_app" echo "wasi_demo_app_digest=$digest_wasi_demo_app" >> $GITHUB_OUTPUT - digest_wasi_demo_oci=$(sudo ctr images ls | grep "ghcr.io/${{ github.repository }}/wasi-demo-oci:${{ inputs.version }}" | awk '{print $3}') + digest_wasi_demo_oci=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci --format '{{ .Id }}' --type image) echo "Digest for wasi-demo-oci: $digest_wasi_demo_oci" echo "wasi_demo_oci_digest=$digest_wasi_demo_oci" >> $GITHUB_OUTPUT - digest_wasi_demo_oci_artifact=$(sudo ctr images ls | grep "ghcr.io/${{ github.repository }}/wasi-demo-oci-artifact:${{ inputs.version }}" | awk '{print $3}') + digest_wasi_demo_oci_artifact=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact --format '{{ .Id }}' --type image) echo "Digest for wasi-demo-oci-artifact: $digest_wasi_demo_oci_artifact" echo "wasi_demo_oci_artifact_digest=$digest_wasi_demo_oci_artifact" >> $GITHUB_OUTPUT diff --git a/Makefile b/Makefile index 36216f7ff..0cbcd89cd 100644 --- a/Makefile +++ b/Makefile @@ -214,6 +214,9 @@ dist/img-oci-artifact.tar: target/wasm32-wasip1/$(OPT_PROFILE)/img-oci-artifact. load: dist/img.tar sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $< +docker/load: dist/img.tar + docker load -i $< + CTR_VERSION := $(shell sudo ctr version | sed -n -e '/Version/ {s/.*: *//p;q;}') load/oci: dist/img-oci.tar dist/img-oci-artifact.tar @echo $(CTR_VERSION)\\nv1.7.7 | sort -crV || @echo $(CTR_VERSION)\\nv1.6.25 | sort -crV || (echo "containerd version must be 1.7.7+ or 1.6.25+ was $(CTR_VERSION)" && exit 1) @@ -221,10 +224,17 @@ load/oci: dist/img-oci.tar dist/img-oci-artifact.tar sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $< sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms dist/img-oci-artifact.tar +docker/load/oci: dist/img-oci.tar dist/img-oci-artifact.tar + docker load -i dist/img-oci.tar + docker load -i dist/img-oci-artifact.tar + .PHONY: load/http load/http: dist/http-img-oci.tar sudo ctr -n $(CONTAINERD_NAMESPACE) image import --all-platforms $< +docker/load/http: dist/http-img-oci.tar + docker load -i $< + target/wasm32-wasip1/$(OPT_PROFILE)/img-oci.tar: target/wasm32-wasip1/$(OPT_PROFILE)/wasi-demo-app.wasm mkdir -p ${CURDIR}/bin/$(OPT_PROFILE)/ cargo run --bin oci-tar-builder -- --name wasi-demo-oci --repo ghcr.io/containerd/runwasi --tag latest --module ./target/wasm32-wasip1/$(OPT_PROFILE)/wasi-demo-app.wasm -o target/wasm32-wasip1/$(OPT_PROFILE)/img-oci.tar From 48f82a9db9c374315eecfcb0f88fd073d27fd7b9 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 27 Jan 2025 22:30:44 +0000 Subject: [PATCH 11/13] RELEASE: remove the empty section Signed-off-by: Jiaxiao (mossaka) Zhou --- RELEASE.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 86232f664..b53a83d47 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -107,10 +107,6 @@ The workflow utilizes a bot account (@containerd-runwasi-release-bot) to publish ## `wasi-demo-app` Release Process - -### wasi-demo-app Release Sequence - - ### Overview To release a new version of the wasi-demo-app images, run the release-wasi-demo-app.yml workflow using the following command, substituting the correct version: From 28dcbb1b5a2575d05c78274f1a41a557e809cd53 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 27 Jan 2025 22:44:38 +0000 Subject: [PATCH 12/13] refactor(ci): use loops and matrix strategy to minimize duplication Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 116 ++++++-------------- .github/workflows/sbom.yml | 24 ++-- .github/workflows/sign.yml | 8 +- 3 files changed, 57 insertions(+), 91 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index 444a8c7bf..b215238e2 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -17,6 +17,7 @@ on: env: CARGO_TERM_COLOR: always + IMAGES: "wasi-demo-app wasi-demo-oci wasi-demo-oci-artifact" jobs: release-wasi-demo: @@ -24,9 +25,9 @@ jobs: packages: write runs-on: ubuntu-latest outputs: - wasi_demo_app_digest: ${{ steps.get_digests.outputs.wasi_demo_app_digest }} - wasi_demo_oci_digest: ${{ steps.get_digests.outputs.wasi_demo_oci_digest }} - wasi_demo_oci_artifact_digest: ${{ steps.get_digests.outputs.wasi_demo_oci_artifact_digest }} + wasi_demo_app: ${{ steps.get_digests.outputs.wasi_demo_app }} + wasi_demo_oci: ${{ steps.get_digests.outputs.wasi_demo_oci }} + wasi_demo_oci_artifact: ${{ steps.get_digests.outputs.wasi_demo_oci_artifact }} steps: - uses: actions/checkout@v4 - name: Setup build env @@ -40,16 +41,16 @@ jobs: - name: Convert repository name to lowercase id: prep - run: echo "::set-output name=repo::$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" + run: echo "repo=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT - - name: login to GitHub container registry + - name: Login to GitHub container registry uses: docker/login-action@v3 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - name: enable containerd image store + - name: Enable containerd image store run: | echo '{ "features": { "containerd-snapshotter": true } }' | sudo tee /etc/docker/daemon.json sudo systemctl restart docker @@ -63,96 +64,49 @@ jobs: - name: Tagging images run: | - docker tag ghcr.io/containerd/runwasi/wasi-demo-app:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:${{ inputs.version }} - docker tag ghcr.io/containerd/runwasi/wasi-demo-app:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:latest - - docker tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:${{ inputs.version }} - docker tag ghcr.io/containerd/runwasi/wasi-demo-oci:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:latest - - docker tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:${{ inputs.version }} - docker tag ghcr.io/containerd/runwasi/wasi-demo-oci-artifact:latest ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:latest + for image in $IMAGES; do + docker tag ghcr.io/containerd/runwasi/$image:latest ghcr.io/${{ steps.prep.outputs.repo }}/$image:${{ inputs.version }} + docker tag ghcr.io/containerd/runwasi/$image:latest ghcr.io/${{ steps.prep.outputs.repo }}/$image:latest + done - name: Push images to ghcr.io if: ${{ inputs.dry_run == false }} run: | - docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:${{ inputs.version }} - docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app:latest - - docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:${{ inputs.version }} - docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci:latest - - docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:${{ inputs.version }} - docker push ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact:latest + for image in $IMAGES; do + docker push ghcr.io/${{ steps.prep.outputs.repo }}/$image:${{ inputs.version }} + docker push ghcr.io/${{ steps.prep.outputs.repo }}/$image:latest + done - name: Display image digests id: get_digests run: | - digest_wasi_demo_app=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-app --format '{{ .Id }}' --type image) - echo "Digest for wasi-demo-app: $digest_wasi_demo_app" - echo "wasi_demo_app_digest=$digest_wasi_demo_app" >> $GITHUB_OUTPUT - - digest_wasi_demo_oci=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci --format '{{ .Id }}' --type image) - echo "Digest for wasi-demo-oci: $digest_wasi_demo_oci" - echo "wasi_demo_oci_digest=$digest_wasi_demo_oci" >> $GITHUB_OUTPUT - - digest_wasi_demo_oci_artifact=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/wasi-demo-oci-artifact --format '{{ .Id }}' --type image) - echo "Digest for wasi-demo-oci-artifact: $digest_wasi_demo_oci_artifact" - echo "wasi_demo_oci_artifact_digest=$digest_wasi_demo_oci_artifact" >> $GITHUB_OUTPUT - - sign-wasi-demo-app: - if: ${{ inputs.dry_run == false }} - needs: - - release-wasi-demo - uses: ./.github/workflows/sign.yml - with: - image-name: "wasi-demo-app" - image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_app_digest }} - - sbom-wasi-demo-app: - if: ${{ inputs.dry_run == false }} - needs: - - release-wasi-demo - uses: ./.github/workflows/sbom.yml - with: - image-name: "wasi-demo-app" - image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_app_digest }} - + for image in $IMAGES; do + DIGEST=$(docker inspect ghcr.io/${{ steps.prep.outputs.repo }}/$image --format '{{ .Id }}' --type image) + echo "Digest for $image: $DIGEST" + sanitized_image="${image//-/_}" + echo "$sanitized_image=$DIGEST" >> $GITHUB_OUTPUT + done - sign-wasi-demo-oci: - if: ${{ inputs.dry_run == false }} - needs: - - release-wasi-demo - uses: ./.github/workflows/sign.yml - with: - image-name: "wasi-demo-oci" - image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_digest }} - - - sbom-wasi-demo-oci: - if: ${{ inputs.dry_run == false }} - needs: - - release-wasi-demo - uses: ./.github/workflows/sbom.yml - with: - image-name: "wasi-demo-oci" - image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_digest }} - - - sign-wasi-demo-oci-artifact: + sign: if: ${{ inputs.dry_run == false }} - needs: + needs: - release-wasi-demo + strategy: + matrix: + image: ["wasi_demo_app", "wasi_demo_oci", "wasi_demo_oci_artifact"] uses: ./.github/workflows/sign.yml with: - image-name: "wasi-demo-oci-artifact" - image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_artifact_digest }} - - - sbom-wasi-demo-oci-artifact: + image-name: ${{ matrix.image }} + image-digest: ${{ needs.release-wasi-demo.outputs[matrix.image] }} + + sbom: if: ${{ inputs.dry_run == false }} needs: - release-wasi-demo + strategy: + matrix: + image: ["wasi_demo_app", "wasi_demo_oci", "wasi_demo_oci_artifact"] uses: ./.github/workflows/sbom.yml with: - image-name: "wasi-demo-oci-artifact" - image-digest: ${{ needs.release-wasi-demo.outputs.wasi_demo_oci_artifact_digest }} + image-name: ${{ matrix.image }} + image-digest: ${{ needs.release-wasi-demo.outputs[matrix.image] }} diff --git a/.github/workflows/sbom.yml b/.github/workflows/sbom.yml index d9f0e0ec4..2506d941d 100644 --- a/.github/workflows/sbom.yml +++ b/.github/workflows/sbom.yml @@ -19,6 +19,12 @@ jobs: runs-on: ubuntu-latest steps: + - name: Sanitize image name + run: | + image="${{ inputs.image-name }}" + image="${image//_/-}" + echo "image=$image" >> $GITHUB_ENV + - name: Install cosign uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 @@ -45,22 +51,22 @@ jobs: SYFT=$(which syft) sudo $SYFT \ -o spdx-json \ - --file ${{ inputs.image-name }}-sbom.spdx \ - ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ inputs.image-digest }} + --file $image-sbom.spdx \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/$image@${{ inputs.image-digest }} - name: Sign SBOM file run: | cosign sign-blob --yes \ - --output-certificate ${{ inputs.image-name }}-sbom.spdx.cert \ - --output-signature ${{ inputs.image-name }}-sbom.spdx.sig \ - ${{ inputs.image-name }}-sbom.spdx + --output-certificate $image-sbom.spdx.cert \ + --output-signature $image-sbom.spdx.sig \ + $image-sbom.spdx - name: Attach SBOM to container image shell: bash run: | cosign attach \ - sbom --sbom ${{ inputs.image-name }}-sbom.spdx \ - ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}@${{ inputs.image-digest }} + sbom --sbom $image-sbom.spdx \ + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/$image@${{ inputs.image-digest }} - name: Sign SBOM file pushed to OCI registry shell: bash @@ -68,10 +74,10 @@ jobs: set -e SBOM_TAG="$(echo ${{ inputs.image-digest }} | sed -e 's/:/-/g').sbom" cosign sign --yes \ - ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/${{ inputs.image-name }}:${SBOM_TAG} + ghcr.io/${{ env.IMG_REPOSITORY_NAME }}/$image:${SBOM_TAG} - name: Upload SBOMs as artifacts uses: actions/upload-artifact@v4 with: name: sbom - path: ${{ inputs.image-name }}-sbom-* \ No newline at end of file + path: $image-sbom-* \ No newline at end of file diff --git a/.github/workflows/sign.yml b/.github/workflows/sign.yml index 1efa94da1..8f8e232ab 100644 --- a/.github/workflows/sign.yml +++ b/.github/workflows/sign.yml @@ -19,6 +19,12 @@ jobs: runs-on: ubuntu-latest steps: + - name: Sanitize image name + run: | + image="${{ inputs.image-name }}" + image="${image//_/-}" + echo "image=$image" >> $GITHUB_ENV + - name: Install cosign uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 @@ -33,4 +39,4 @@ jobs: run: | IMG_REPOSITORY_NAME=$( echo ${{ github.repository }} | awk '{print tolower($0)}' ) cosign sign --yes \ - ghcr.io/${IMG_REPOSITORY_NAME}/${{ inputs.image-name }}@${{ inputs.image-digest }} \ No newline at end of file + ghcr.io/${IMG_REPOSITORY_NAME}/$image@${{ inputs.image-digest }} \ No newline at end of file From 1d0bf4f5d948d562397e7c8ed056c14556a0e0a1 Mon Sep 17 00:00:00 2001 From: "Jiaxiao (mossaka) Zhou" Date: Mon, 27 Jan 2025 23:45:31 +0000 Subject: [PATCH 13/13] feat(ci): add release for wasi-http image Signed-off-by: Jiaxiao (mossaka) Zhou --- .github/workflows/release-wasi-demo-app.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-wasi-demo-app.yml b/.github/workflows/release-wasi-demo-app.yml index b215238e2..a25882087 100644 --- a/.github/workflows/release-wasi-demo-app.yml +++ b/.github/workflows/release-wasi-demo-app.yml @@ -17,7 +17,7 @@ on: env: CARGO_TERM_COLOR: always - IMAGES: "wasi-demo-app wasi-demo-oci wasi-demo-oci-artifact" + IMAGES: "wasi-demo-app wasi-demo-oci wasi-demo-oci-artifact wasi-http" jobs: release-wasi-demo: @@ -28,6 +28,7 @@ jobs: wasi_demo_app: ${{ steps.get_digests.outputs.wasi_demo_app }} wasi_demo_oci: ${{ steps.get_digests.outputs.wasi_demo_oci }} wasi_demo_oci_artifact: ${{ steps.get_digests.outputs.wasi_demo_oci_artifact }} + wasi_http: ${{ steps.get_digests.outputs.wasi_http }} steps: - uses: actions/checkout@v4 - name: Setup build env @@ -60,6 +61,7 @@ jobs: run: | make docker/load make docker/load/oci + make docker/load/http docker image ls - name: Tagging images @@ -93,7 +95,7 @@ jobs: - release-wasi-demo strategy: matrix: - image: ["wasi_demo_app", "wasi_demo_oci", "wasi_demo_oci_artifact"] + image: ["wasi_demo_app", "wasi_demo_oci", "wasi_demo_oci_artifact", "wasi_http"] uses: ./.github/workflows/sign.yml with: image-name: ${{ matrix.image }} @@ -105,7 +107,7 @@ jobs: - release-wasi-demo strategy: matrix: - image: ["wasi_demo_app", "wasi_demo_oci", "wasi_demo_oci_artifact"] + image: ["wasi_demo_app", "wasi_demo_oci", "wasi_demo_oci_artifact", "wasi_http"] uses: ./.github/workflows/sbom.yml with: image-name: ${{ matrix.image }}