zlib-release #73
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: Nanvix CI | |
| on: | |
| schedule: | |
| - cron: "0 0 * * *" | |
| push: | |
| branches: | |
| - nanvix/** | |
| pull_request: | |
| branches: | |
| - nanvix/** | |
| workflow_dispatch: | |
| repository_dispatch: | |
| # Triggered by zlib when it completes a release (dependency chain) | |
| types: [zlib-release] | |
| permissions: | |
| contents: write | |
| actions: write | |
| issues: write | |
| jobs: | |
| # Extract Nanvix SHA once - all matrix builds use the same Nanvix release | |
| get-nanvix-info: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| sha: ${{ steps.extract.outputs.sha }} | |
| sha_full: ${{ steps.extract.outputs.sha_full }} | |
| steps: | |
| - name: Download Nanvix Release Info | |
| id: extract | |
| run: | | |
| set -euo pipefail | |
| # Download Nanvix release artifacts list | |
| curl -fsSL https://raw.githubusercontent.com/nanvix/nanvix/refs/heads/dev/scripts/get-nanvix.sh | bash -s -- --force nanvix-artifacts | |
| # Find any artifact to extract the SHA | |
| ARTIFACT_FILE=$(find nanvix-artifacts -maxdepth 1 -type f -name "*.tar.bz2" | head -1) | |
| if [[ -z "$ARTIFACT_FILE" ]]; then | |
| echo "::error::No Nanvix artifact found" | |
| exit 1 | |
| fi | |
| # Extract Nanvix commit SHA from artifact filename | |
| NANVIX_SHA_FULL=$(basename "$ARTIFACT_FILE" | sed -E 's/.*-([a-f0-9]{40})\.tar\.bz2$/\1/') | |
| NANVIX_SHA="${NANVIX_SHA_FULL::7}" | |
| echo "Nanvix commit SHA: $NANVIX_SHA_FULL (short: $NANVIX_SHA)" | |
| echo "sha=$NANVIX_SHA" >> "$GITHUB_OUTPUT" | |
| echo "sha_full=$NANVIX_SHA_FULL" >> "$GITHUB_OUTPUT" | |
| build: | |
| needs: get-nanvix-info | |
| runs-on: ubuntu-latest | |
| outputs: | |
| zlib_tag: ${{ steps.zlib-dep.outputs.zlib_tag }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - platform: hyperlight | |
| process-mode: multi-process | |
| - platform: hyperlight | |
| process-mode: single-process | |
| - platform: microvm | |
| process-mode: single-process | |
| - platform: microvm | |
| process-mode: multi-process | |
| name: ${{ matrix.platform }}-${{ matrix.process-mode }} | |
| container: | |
| image: nanvix/toolchain:latest-minimal | |
| options: --device /dev/kvm | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| NANVIX_SHA: ${{ needs.get-nanvix-info.outputs.sha }} | |
| NANVIX_SHA_FULL: ${{ needs.get-nanvix-info.outputs.sha_full }} | |
| USER: runner | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download and Extract Nanvix Release | |
| run: | | |
| set -euo pipefail | |
| # Download all Nanvix release artifacts | |
| curl -fsSL https://raw.githubusercontent.com/nanvix/nanvix/refs/heads/dev/scripts/get-nanvix.sh | bash -s -- --force nanvix-artifacts | |
| # Find and extract the artifact matching platform and process-mode | |
| ARTIFACT_PATTERN="${{ matrix.platform }}.*${{ matrix.process-mode }}.*\.tar\.bz2" | |
| ARTIFACT_FILE=$(find nanvix-artifacts -maxdepth 1 -type f -name "*.tar.bz2" | grep -E "$ARTIFACT_PATTERN" | head -1) | |
| if [[ -z "$ARTIFACT_FILE" ]]; then | |
| echo "::error::No ${{ matrix.platform }} ${{ matrix.process-mode }} artifact found" | |
| exit 1 | |
| fi | |
| mkdir -p nanvix-artifacts/extracted | |
| tar -xjf "$ARTIFACT_FILE" -C nanvix-artifacts/extracted | |
| NANVIX_HOME=$(find nanvix-artifacts/extracted -maxdepth 2 -type d -name "bin" -exec dirname {} \; | head -1) | |
| mkdir -p "$NANVIX_HOME/include" | |
| echo "NANVIX_HOME=$NANVIX_HOME" >> "$GITHUB_ENV" | |
| - name: Download and Install zlib Dependency | |
| id: zlib-dep | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| echo "Downloading zlib for ${{ matrix.platform }}-${{ matrix.process-mode }} (Nanvix SHA: $NANVIX_SHA)..." | |
| ZLIB_ARTIFACT="zlib-${{ matrix.platform }}-${{ matrix.process-mode }}.tar.bz2" | |
| mkdir -p zlib-dep | |
| # Get list of zlib releases and find one built with matching Nanvix SHA | |
| # Release tags follow format: {commit-sha}-nanvix-{nanvix-sha} | |
| echo "Looking for zlib release built with Nanvix SHA $NANVIX_SHA..." | |
| ZLIB_RELEASES=$(curl -fsSL -H "Authorization: Bearer ${GH_TOKEN}" \ | |
| "https://api.github.com/repos/nanvix/zlib/releases?per_page=50" 2>/dev/null || echo "[]") | |
| # Find a release with tag ending in -nanvix-{NANVIX_SHA} | |
| MATCHING_RELEASE_TAG="" | |
| for tag in $(echo "$ZLIB_RELEASES" | jq -r '.[].tag_name' 2>/dev/null); do | |
| if [[ "$tag" == *"-nanvix-${NANVIX_SHA}" ]]; then | |
| MATCHING_RELEASE_TAG="$tag" | |
| echo "Found matching zlib release: $tag" | |
| break | |
| fi | |
| done | |
| # If no matching release found, fall back to latest | |
| if [[ -z "$MATCHING_RELEASE_TAG" ]]; then | |
| echo "::warning::No zlib release found matching Nanvix SHA $NANVIX_SHA, falling back to latest" | |
| ZLIB_URL="https://github.com/nanvix/zlib/releases/latest/download/${ZLIB_ARTIFACT}" | |
| # Get the actual tag of latest release for recording | |
| MATCHING_RELEASE_TAG=$(curl -fsSL -H "Authorization: Bearer ${GH_TOKEN}" \ | |
| "https://api.github.com/repos/nanvix/zlib/releases/latest" 2>/dev/null | jq -r '.tag_name // "latest"') | |
| else | |
| ZLIB_URL="https://github.com/nanvix/zlib/releases/download/${MATCHING_RELEASE_TAG}/${ZLIB_ARTIFACT}" | |
| fi | |
| # Record the exact zlib tag used for downstream consumers | |
| echo "ZLIB_TAG=${MATCHING_RELEASE_TAG}" >> "$GITHUB_ENV" | |
| echo "zlib_tag=${MATCHING_RELEASE_TAG}" >> "$GITHUB_OUTPUT" | |
| echo "Recording zlib dependency tag: ${MATCHING_RELEASE_TAG}" | |
| echo "Downloading zlib from: $ZLIB_URL" | |
| if curl -fsSL -o "zlib-dep/${ZLIB_ARTIFACT}" "$ZLIB_URL"; then | |
| tar -xjf "zlib-dep/${ZLIB_ARTIFACT}" -C zlib-dep | |
| # Find extracted directory and copy files to sysroot | |
| ZLIB_DIR=$(find zlib-dep -mindepth 1 -maxdepth 1 -type d -name "zlib-*" | head -1) | |
| if [[ -n "$ZLIB_DIR" ]]; then | |
| echo "Installing zlib from $ZLIB_DIR to $NANVIX_HOME..." | |
| cp -f "${ZLIB_DIR}/lib/libz.a" "${NANVIX_HOME}/lib/" 2>/dev/null || true | |
| cp -f "${ZLIB_DIR}/include/"*.h "${NANVIX_HOME}/include/" 2>/dev/null || true | |
| echo "zlib installed successfully" | |
| else | |
| echo "::warning::Could not find extracted zlib directory" | |
| fi | |
| else | |
| echo "::error::Could not download zlib release" | |
| exit 1 | |
| fi | |
| - name: Build | |
| run: | | |
| make -f Makefile.nanvix CONFIG_NANVIX=y NANVIX_HOME="$NANVIX_HOME" NANVIX_TOOLCHAIN="/opt/nanvix" all | |
| - name: Test | |
| run: | | |
| make -f Makefile.nanvix CONFIG_NANVIX=y NANVIX_HOME="$NANVIX_HOME" NANVIX_TOOLCHAIN="/opt/nanvix" test | |
| - name: Package Artifacts | |
| run: | | |
| set -euo pipefail | |
| ARTIFACT_NAME="sqlite-${{ matrix.platform }}-${{ matrix.process-mode }}" | |
| DIST_DIR="dist/${ARTIFACT_NAME}" | |
| mkdir -p "${DIST_DIR}/bin" "${DIST_DIR}/lib" "${DIST_DIR}/include" | |
| # Copy executables | |
| cp -f sqlite3.elf "${DIST_DIR}/bin/" 2>/dev/null || true | |
| # Copy libraries | |
| cp -f .libs/libsqlite3.a "${DIST_DIR}/lib/" 2>/dev/null || cp -f libsqlite3.a "${DIST_DIR}/lib/" 2>/dev/null || true | |
| # Copy headers | |
| cp -f sqlite3.h "${DIST_DIR}/include/" 2>/dev/null || true | |
| # Create tarball | |
| tar -cjf "dist/${ARTIFACT_NAME}.tar.bz2" -C dist "${ARTIFACT_NAME}" | |
| echo "ARTIFACT_TARBALL=dist/${ARTIFACT_NAME}.tar.bz2" >> "$GITHUB_ENV" | |
| - name: Upload Build Artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: sqlite-${{ matrix.platform }}-${{ matrix.process-mode }} | |
| path: ${{ env.ARTIFACT_TARBALL }} | |
| retention-days: 7 | |
| release: | |
| needs: [get-nanvix-info, build] | |
| if: github.event_name != 'pull_request' | |
| runs-on: ubuntu-latest | |
| env: | |
| NANVIX_SHA: ${{ needs.get-nanvix-info.outputs.sha }} | |
| NANVIX_SHA_FULL: ${{ needs.get-nanvix-info.outputs.sha_full }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Download All Artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: release-artifacts | |
| pattern: sqlite-* | |
| - name: Prepare Release Assets | |
| run: | | |
| set -euo pipefail | |
| mkdir -p release-assets | |
| find release-artifacts -name "*.tar.bz2" -exec cp {} release-assets/ \; | |
| ls -la release-assets/ | |
| - name: Get Dependency Tags | |
| id: deps | |
| env: | |
| ZLIB_TAG: ${{ needs.build.outputs.zlib_tag }} | |
| run: | | |
| set -euo pipefail | |
| # Dependency tags come from job outputs (all matrix builds use the same) | |
| echo "Using zlib tag from job outputs: ${ZLIB_TAG}" | |
| # Extract commit SHA from tag (format: {commit-sha}-nanvix-{nanvix-sha}) | |
| ZLIB_SHA=$(echo "$ZLIB_TAG" | sed -E 's/^([a-f0-9]+)-nanvix-.*$/\1/') | |
| echo "zlib_tag=${ZLIB_TAG}" >> "$GITHUB_OUTPUT" | |
| echo "zlib_sha=${ZLIB_SHA}" >> "$GITHUB_OUTPUT" | |
| echo "Using zlib tag: ${ZLIB_TAG} (SHA: ${ZLIB_SHA})" | |
| - name: Get Nanvix Release Info | |
| id: nanvix-release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| echo "Using Nanvix SHA from job outputs: $NANVIX_SHA (full: $NANVIX_SHA_FULL)" | |
| # Query Nanvix release API for additional metadata | |
| API_URL="https://api.github.com/repos/nanvix/nanvix/releases/tags/latest" | |
| RELEASE_INFO=$(curl -fsSL -H "Authorization: Bearer ${GH_TOKEN}" "$API_URL") | |
| NANVIX_NAME=$(echo "$RELEASE_INFO" | jq -r '.name // "latest"') | |
| NANVIX_PUBLISHED=$(echo "$RELEASE_INFO" | jq -r '.published_at') | |
| echo "name=${NANVIX_NAME}" >> "$GITHUB_OUTPUT" | |
| echo "published=${NANVIX_PUBLISHED}" >> "$GITHUB_OUTPUT" | |
| - name: Create Latest Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| NANVIX_NAME: ${{ steps.nanvix-release.outputs.name }} | |
| NANVIX_PUBLISHED: ${{ steps.nanvix-release.outputs.published }} | |
| ZLIB_TAG: ${{ steps.deps.outputs.zlib_tag }} | |
| ZLIB_SHA: ${{ steps.deps.outputs.zlib_sha }} | |
| run: | | |
| # Release tag format: {commit-sha}-nanvix-{nanvix-sha} | |
| # This enables easy lookup of releases built with a specific Nanvix version | |
| RELEASE_TAG="${GITHUB_SHA::7}-nanvix-${NANVIX_SHA}" | |
| # Delete existing release if it exists (idempotent re-runs) | |
| if gh release view "$RELEASE_TAG" &>/dev/null; then | |
| echo "Deleting existing release: $RELEASE_TAG" | |
| gh release delete "$RELEASE_TAG" --yes --cleanup-tag || true | |
| fi | |
| gh release create "$RELEASE_TAG" \ | |
| --title "Build ${GITHUB_SHA::7}" \ | |
| --notes "Automated build from branch ${{ github.ref_name }} at commit ${{ github.sha }}. | |
| **Build Information:** | |
| - Workflow Run: [#${{ github.run_number }}](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) | |
| - Commit: [${{ github.sha }}](${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}) | |
| - Date: $(date -u +"%Y-%m-%d %H:%M:%S UTC") | |
| **Nanvix Release:** | |
| - Name: ${NANVIX_NAME} | |
| - Published: ${NANVIX_PUBLISHED} | |
| - Commit: [${NANVIX_SHA_FULL}](https://github.com/nanvix/nanvix/commit/${NANVIX_SHA_FULL}) | |
| **Dependencies:** | |
| - zlib: [\`${ZLIB_TAG}\`](https://github.com/nanvix/zlib/releases/tag/${ZLIB_TAG})" \ | |
| --latest \ | |
| release-assets/*.tar.bz2 | |
| # Trigger dependent workflows (cpython depends on sqlite) | |
| - name: Trigger Dependent Workflows | |
| if: success() | |
| env: | |
| GH_TOKEN: ${{ secrets.DISPATCH_TOKEN }} | |
| run: | | |
| echo "Triggering cpython workflow..." | |
| gh api repos/nanvix/cpython/dispatches \ | |
| -X POST \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -f event_type="sqlite-release" \ | |
| -f "client_payload[nanvix_sha]=${NANVIX_SHA}" \ | |
| -f "client_payload[sqlite_tag]=${GITHUB_SHA::7}-nanvix-${NANVIX_SHA}" \ | |
| -f "client_payload[zlib_tag]=${ZLIB_TAG}" || echo "::warning::Failed to trigger cpython workflow" | |
| report-failure: | |
| needs: | |
| - build | |
| if: >- | |
| ${{ always() && | |
| (github.event_name == 'repository_dispatch' || github.event_name == 'schedule' || github.event_name == 'push') && | |
| needs.build.result == 'failure' }} | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Create failure issue | |
| uses: actions/github-script@v7 | |
| env: | |
| BUILD_RESULT: ${{ needs.build.result }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const runUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const owner = context.repo.owner; | |
| const repo = context.repo.repo; | |
| const title = `CI failure (run ${context.runNumber})`; | |
| const body = [ | |
| `The sqlite CI workflow failed.`, | |
| `- Trigger: ${context.eventName}`, | |
| `- Run: [#${context.runNumber}](${runUrl})`, | |
| `- SHA: ${context.sha}`, | |
| `- build: ${process.env.BUILD_RESULT}`, | |
| '', | |
| 'Please investigate and take any corrective actions.' | |
| ].join('\n'); | |
| await github.rest.issues.create({ | |
| owner, | |
| repo, | |
| title, | |
| body, | |
| assignees: ['ppenna'] | |
| }); |