Release | Kata Bundle with Asterinas as the Guest Kernel #141
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
| name: Release | Kata Bundle with Asterinas as the Guest Kernel | |
| on: | |
| push: | |
| branches: | |
| - asterinas | |
| schedule: | |
| - cron: '10 03 * * *' | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: Git tag to create or update for this Asterinas release | |
| required: true | |
| type: string | |
| release_name: | |
| description: Optional display name for the GitHub release | |
| required: false | |
| type: string | |
| draft_release: | |
| description: Create the GitHub release as a draft | |
| required: true | |
| default: true | |
| type: boolean | |
| force_runtime_build: | |
| description: Rebuild kata-runtime even if src/runtime matches the upstream release tag | |
| required: true | |
| default: false | |
| type: boolean | |
| kata_static_release_repository: | |
| description: Repository used as the official Kata base release source | |
| required: true | |
| default: kata-containers/kata-containers | |
| type: string | |
| permissions: | |
| contents: write | |
| env: | |
| FORCE_RUNTIME_BUILD: ${{ inputs.force_runtime_build || false }} | |
| KATA_STATIC_RELEASE_REPOSITORY: ${{ inputs.kata_static_release_repository || 'kata-containers/kata-containers' }} | |
| jobs: | |
| load-asterinas-metadata: | |
| name: Load Asterinas Metadata | |
| runs-on: ubuntu-latest | |
| outputs: | |
| asterinas_repository: ${{ steps.load.outputs.asterinas_repository }} | |
| asterinas_ref: ${{ steps.load.outputs.asterinas_ref }} | |
| asterinas_commit: ${{ steps.load.outputs.asterinas_commit }} | |
| asterinas_version: ${{ steps.load.outputs.asterinas_version }} | |
| docker_image_version: ${{ steps.load.outputs.docker_image_version }} | |
| asterinas_builder_image: ${{ steps.load.outputs.asterinas_builder_image }} | |
| asterinas_metadata_source: ${{ steps.load.outputs.asterinas_metadata_source }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Load Asterinas Metadata | |
| id: load | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| bash tools/kata/asterinas_metadata.sh resolve | |
| - name: Write Workflow Summary | |
| shell: bash | |
| run: | | |
| { | |
| echo '## Loaded Asterinas metadata' | |
| echo | |
| echo "- Repository: \`${{ steps.load.outputs.asterinas_repository }}\`" | |
| echo "- Ref: \`${{ steps.load.outputs.asterinas_ref }}\`" | |
| echo "- Commit: \`${{ steps.load.outputs.asterinas_commit }}\`" | |
| echo "- \`VERSION\`: \`${{ steps.load.outputs.asterinas_version }}\`" | |
| echo "- \`DOCKER_IMAGE_VERSION\`: \`${{ steps.load.outputs.docker_image_version }}\`" | |
| echo "- Builder image: \`${{ steps.load.outputs.asterinas_builder_image }}\`" | |
| echo "- Metadata source: \`${{ steps.load.outputs.asterinas_metadata_source }}\`" | |
| } >> "${GITHUB_STEP_SUMMARY}" | |
| check-scheduled-release: | |
| name: Check Whether Scheduled Release Is Needed | |
| needs: | |
| - load-asterinas-metadata | |
| runs-on: ubuntu-latest | |
| outputs: | |
| should_build: ${{ steps.gate.outputs.should_build }} | |
| skip_reason: ${{ steps.gate.outputs.skip_reason }} | |
| steps: | |
| - name: Check Scheduled Release Gate | |
| id: gate | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| ASTERINAS_METADATA_SOURCE: ${{ needs.load-asterinas-metadata.outputs.asterinas_metadata_source }} | |
| DOCKER_IMAGE_VERSION: ${{ needs.load-asterinas-metadata.outputs.docker_image_version }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| should_build=true | |
| skip_reason="" | |
| if [[ "${GITHUB_EVENT_NAME}" == "schedule" ]]; then | |
| if [[ "${ASTERINAS_METADATA_SOURCE}" != "upstream" ]]; then | |
| should_build=false | |
| skip_reason="Scheduled release runs only when Asterinas metadata resolves from asterinas/asterinas upstream." | |
| elif gh api "repos/${GITHUB_REPOSITORY}/releases" --paginate | python3 -c 'import json,re,sys; target=sys.argv[1]; pattern=re.compile(r"Asterinas Docker image version: `([^`]+)`"); releases=json.load(sys.stdin); sys.exit(0 if any(target in pattern.findall((release.get(\"body\") or \"\")) for release in releases) else 1)' "${DOCKER_IMAGE_VERSION}" | |
| then | |
| should_build=false | |
| skip_reason="A release for Asterinas Docker image version ${DOCKER_IMAGE_VERSION} already exists." | |
| fi | |
| fi | |
| echo "should_build=${should_build}" >> "${GITHUB_OUTPUT}" | |
| { | |
| echo 'skip_reason<<EOF' | |
| printf '%s\n' "${skip_reason}" | |
| echo 'EOF' | |
| } >> "${GITHUB_OUTPUT}" | |
| { | |
| echo '## Scheduled release gate' | |
| echo | |
| echo "- Event: \`${GITHUB_EVENT_NAME}\`" | |
| echo "- Asterinas Docker image version: \`${DOCKER_IMAGE_VERSION}\`" | |
| echo "- Metadata source: \`${ASTERINAS_METADATA_SOURCE}\`" | |
| echo "- Continue workflow: \`${should_build}\`" | |
| if [[ -n "${skip_reason}" ]]; then | |
| echo "- Skip reason: ${skip_reason}" | |
| fi | |
| } >> "${GITHUB_STEP_SUMMARY}" | |
| build-asterinas-kernel: | |
| name: Build Asterinas Kernel Artifact | |
| if: ${{ needs.check-scheduled-release.outputs.should_build == 'true' }} | |
| runs-on: ubuntu-22.04 | |
| needs: | |
| - load-asterinas-metadata | |
| - check-scheduled-release | |
| outputs: | |
| asterinas_commit: ${{ steps.asterinas_commit.outputs.value }} | |
| container: | |
| image: ${{ needs.load-asterinas-metadata.outputs.asterinas_builder_image }} | |
| steps: | |
| - name: Check Out Asterinas | |
| uses: actions/checkout@v4 | |
| with: | |
| repository: ${{ needs.load-asterinas-metadata.outputs.asterinas_repository }} | |
| ref: ${{ needs.load-asterinas-metadata.outputs.asterinas_commit }} | |
| path: asterinas | |
| - name: Record Asterinas Commit | |
| id: asterinas_commit | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| echo "value=$(git -C asterinas rev-parse HEAD)" >> "${GITHUB_OUTPUT}" | |
| - name: Build qemu-direct Kernels | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| kernel_artifact_dir="${GITHUB_WORKSPACE}/build/asterinas-kernel" | |
| kernel_artifact_name="aster-kernel-osdk-bin.qemu_elf" | |
| tdx_kernel_build_name="aster-kernel-osdk-bin" | |
| tdx_kernel_artifact_name="${tdx_kernel_build_name}-tdx" | |
| kernel_artifact="${kernel_artifact_dir}/${kernel_artifact_name}" | |
| tdx_kernel_artifact="${kernel_artifact_dir}/${tdx_kernel_artifact_name}" | |
| mkdir -p "${kernel_artifact_dir}" | |
| make -C asterinas kernel BOOT_METHOD=qemu-direct | |
| install -m 0755 "asterinas/target/osdk/${kernel_artifact_name}" "${kernel_artifact}" | |
| make -C asterinas kernel BOOT_METHOD=qemu-direct INTEL_TDX=1 | |
| install -m 0755 "asterinas/target/osdk/${tdx_kernel_build_name}" "${tdx_kernel_artifact}" | |
| test -f "${kernel_artifact}" | |
| test -f "${tdx_kernel_artifact}" | |
| - name: Upload Kernel Artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: asterinas-kernel-amd64 | |
| path: | | |
| build/asterinas-kernel/aster-kernel-osdk-bin.qemu_elf | |
| build/asterinas-kernel/aster-kernel-osdk-bin-tdx | |
| if-no-files-found: error | |
| retention-days: 7 | |
| build-release-bundle: | |
| name: Build and Publish Kata Bundle with Asterinas as the Guest Kernel | |
| if: ${{ needs.check-scheduled-release.outputs.should_build == 'true' }} | |
| runs-on: ubuntu-22.04 | |
| needs: | |
| - load-asterinas-metadata | |
| - check-scheduled-release | |
| - build-asterinas-kernel | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Check Out kata-containers | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Derive Go Version from versions.yaml | |
| id: go_version | |
| shell: bash | |
| run: | | |
| go_version="$(awk ' | |
| $1 == "languages:" { in_languages=1; next } | |
| in_languages && $1 == "golang:" { in_golang=1; next } | |
| in_golang && $1 == "version:" { | |
| gsub(/"/, "", $2) | |
| print $2 | |
| exit | |
| } | |
| ' versions.yaml)" | |
| test -n "${go_version}" | |
| echo "value=${go_version}" >> "${GITHUB_OUTPUT}" | |
| - name: Set Up Go | |
| uses: actions/setup-go@v6 | |
| with: | |
| go-version: ${{ steps.go_version.outputs.value }} | |
| - name: Install Packaging Dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y cpio zstd | |
| - name: Download Asterinas Kernel Artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: asterinas-kernel-amd64 | |
| path: build/asterinas-kernel | |
| - name: Build Kata Tarball with Asterinas as the Guest Kernel | |
| id: bundle | |
| env: | |
| ARCHITECTURE: amd64 | |
| ASTERINAS_KERNEL: ${{ github.workspace }}/build/asterinas-kernel/aster-kernel-osdk-bin.qemu_elf | |
| ASTERINAS_TDX_KERNEL: ${{ github.workspace }}/build/asterinas-kernel/aster-kernel-osdk-bin-tdx | |
| ASTERINAS_REPOSITORY: ${{ needs.load-asterinas-metadata.outputs.asterinas_repository }} | |
| ASTERINAS_REF: ${{ needs.load-asterinas-metadata.outputs.asterinas_ref }} | |
| ASTERINAS_COMMIT: ${{ needs.build-asterinas-kernel.outputs.asterinas_commit }} | |
| ASTERINAS_VERSION: ${{ needs.load-asterinas-metadata.outputs.asterinas_version }} | |
| ASTERINAS_DOCKER_IMAGE_VERSION: ${{ needs.load-asterinas-metadata.outputs.docker_image_version }} | |
| ASTERINAS_BUILDER_IMAGE: ${{ needs.load-asterinas-metadata.outputs.asterinas_builder_image }} | |
| FORCE_RUNTIME_BUILD: ${{ env.FORCE_RUNTIME_BUILD }} | |
| KATA_STATIC_RELEASE_REPOSITORY: ${{ env.KATA_STATIC_RELEASE_REPOSITORY }} | |
| run: | | |
| chmod +x ./tools/packaging/release/build-asterinas-release.sh | |
| ./tools/packaging/release/build-asterinas-release.sh | |
| - name: Verify Packaged Release Contents | |
| run: | | |
| set -euo pipefail | |
| tar -I zstd -tf "${{ steps.bundle.outputs.release_asset }}" | grep -E '(^|/)opt/kata/share/kata-containers/aster-kernel-osdk-bin\.qemu_elf$' | |
| tar -I zstd -tf "${{ steps.bundle.outputs.release_asset }}" | grep -E '(^|/)opt/kata/share/kata-containers/aster-kernel-osdk-bin-tdx$' | |
| tar -I zstd -tf "${{ steps.bundle.outputs.release_asset }}" | grep -F "opt/kata/share/kata-containers/tools/kata/kata_env.sh" | |
| tar -I zstd -tf "${{ steps.bundle.outputs.release_asset }}" | grep -F "opt/kata/share/kata-containers/tools/kata/run_kata.sh" | |
| tar -I zstd -tf "${{ steps.bundle.outputs.release_asset }}" | grep -F "opt/kata/share/kata-containers/tools/kata/kata_services.sh" | |
| - name: Upload Workflow Artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: asterinas-kata-release | |
| path: | | |
| ${{ steps.bundle.outputs.release_asset }} | |
| ${{ steps.bundle.outputs.manifest_file }} | |
| ${{ steps.bundle.outputs.checksums_file }} | |
| ${{ steps.bundle.outputs.build_summary }} | |
| ${{ steps.bundle.outputs.release_notes }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| - name: Derive Release Metadata | |
| id: release | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event_name == 'schedule' }} | |
| env: | |
| WORKFLOW_RELEASE_TAG: ${{ inputs.release_tag }} | |
| WORKFLOW_RELEASE_NAME: ${{ inputs.release_name }} | |
| WORKFLOW_DRAFT_RELEASE: ${{ inputs.draft_release }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| version="$(<VERSION)" | |
| if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then | |
| release_tag="${WORKFLOW_RELEASE_TAG}" | |
| release_name="${WORKFLOW_RELEASE_NAME}" | |
| draft_release="${WORKFLOW_DRAFT_RELEASE}" | |
| else | |
| version="${version}-$(date -u +%Y%m%d)" | |
| release_tag="${version}-asterinas" | |
| release_name="Kata with Asterinas as the Guest Kernel ${version}" | |
| draft_release="false" | |
| fi | |
| echo "tag=${release_tag}" >> "${GITHUB_OUTPUT}" | |
| echo "name=${release_name}" >> "${GITHUB_OUTPUT}" | |
| echo "draft=${draft_release}" >> "${GITHUB_OUTPUT}" | |
| - name: Publish GitHub Release | |
| if: ${{ github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event_name == 'schedule' }} | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| RELEASE_TAG: ${{ steps.release.outputs.tag }} | |
| RELEASE_NAME: ${{ steps.release.outputs.name }} | |
| DRAFT_RELEASE: ${{ steps.release.outputs.draft }} | |
| RELEASE_ASSET: ${{ steps.bundle.outputs.release_asset }} | |
| MANIFEST_FILE: ${{ steps.bundle.outputs.manifest_file }} | |
| CHECKSUMS_FILE: ${{ steps.bundle.outputs.checksums_file }} | |
| BUILD_SUMMARY: ${{ steps.bundle.outputs.build_summary }} | |
| RELEASE_NOTES: ${{ steps.bundle.outputs.release_notes }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| title="${RELEASE_NAME:-${RELEASE_TAG}}" | |
| asset_args=( | |
| "${RELEASE_ASSET}" | |
| "${MANIFEST_FILE}" | |
| "${CHECKSUMS_FILE}" | |
| "${BUILD_SUMMARY}" | |
| ) | |
| if gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then | |
| edit_draft_flag=(--draft=false) | |
| if [[ "${DRAFT_RELEASE}" == "true" ]]; then | |
| edit_draft_flag=(--draft) | |
| fi | |
| gh release edit "${RELEASE_TAG}" \ | |
| --title "${title}" \ | |
| --notes-file "${RELEASE_NOTES}" \ | |
| --target "${GITHUB_SHA}" \ | |
| "${edit_draft_flag[@]}" | |
| gh release upload "${RELEASE_TAG}" "${asset_args[@]}" --clobber | |
| else | |
| draft_flag=() | |
| if [[ "${DRAFT_RELEASE}" == "true" ]]; then | |
| draft_flag+=(--draft) | |
| fi | |
| gh release create "${RELEASE_TAG}" \ | |
| "${asset_args[@]}" \ | |
| --title "${title}" \ | |
| --notes-file "${RELEASE_NOTES}" \ | |
| --target "${GITHUB_SHA}" \ | |
| "${draft_flag[@]}" | |
| fi |