Migrate from Docker to Podman #164
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
| # Unified CI workflow that runs on both main pushes and pull requests | |
| # | |
| # This workflow handles three main responsibilities: | |
| # 1. Release management (main only): Creates releases and changesets PRs | |
| # 2. Deployment: Deploys to Vercel (production for main, preview for PRs) | |
| # 3. Container: Builds and optionally publishes container images using Podman | |
| # | |
| # Behavior by event type: | |
| # - On PR: Validates changes by building container image and deploying Vercel preview | |
| # - On main push: Full release pipeline including container registry push and git tags | |
| # | |
| # Job execution logic: | |
| # - release-job: Only runs on main push to handle releases | |
| # - vercel-job: Runs on PRs (preview) and main (production) when no changesets pending | |
| # - podman-job: Runs on PRs (build only) and main (build + push) when no changesets pending | |
| name: CI | |
| on: | |
| push: | |
| branches: | |
| - 'main' | |
| pull_request: | |
| branches: | |
| - 'main' | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| env: | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| jobs: | |
| release-job: | |
| runs-on: ubuntu-latest | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| outputs: | |
| hasChangesets: ${{ steps.changesets.outputs.hasChangesets }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: 'npm' | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Create Release Pull Request or Publish | |
| id: changesets | |
| uses: changesets/action@v1 | |
| with: | |
| publish: npm run release | |
| createGithubReleases: true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| vercel-job: | |
| runs-on: ubuntu-latest | |
| needs: release-job | |
| # Run if release-job was skipped (PRs) or if it completed with no changesets | |
| # This ensures we deploy previews for PRs and production for main (when no release is in progress) | |
| if: | | |
| always() && | |
| (needs.release-job.result == 'skipped' || needs.release-job.outputs.hasChangesets == 'false') | |
| permissions: | |
| contents: read | |
| # Update the Production/Preview environment with the Vercel deployed URL | |
| environment: | |
| name: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && 'Production' || 'Preview' }} | |
| url: ${{ steps.vercel-deploy.outputs.deployment_url }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: actions/setup-node@v6 | |
| with: | |
| node-version-file: '.nvmrc' | |
| - id: vercel-deploy | |
| run: | | |
| npx -y vercel deploy --token=${{ secrets.VERCEL_TOKEN }} \ | |
| --target=${{ github.event_name == 'push' && 'production' || 'preview' }} \ | |
| --build-env MDX=docs \ | |
| --build-env NEXT_PUBLIC_LIBNAME="Poimandres" \ | |
| --build-env NEXT_PUBLIC_LIBNAME_SHORT="pmndrs" \ | |
| --build-env NEXT_PUBLIC_LIBNAME_DOTSUFFIX_LABEL="docs" \ | |
| --build-env NEXT_PUBLIC_LIBNAME_DOTSUFFIX_HREF="https://pmnd.rs" \ | |
| --build-env BASE_PATH= \ | |
| --build-env DIST_DIR= \ | |
| --build-env OUTPUT= \ | |
| --build-env HOME_REDIRECT= \ | |
| --build-env MDX_BASEURL="https://github.com/${{ github.repository }}/raw/${{ github.head_ref || github.ref_name }}/docs" \ | |
| --build-env EDIT_BASEURL="https://github.com/${{ github.repository }}/edit/${{ github.head_ref || github.ref_name }}/docs" \ | |
| --build-env SOURCECODE_BASEURL="https://github.com/${{ github.repository }}/tree/${{ github.head_ref || github.ref_name }}" \ | |
| --build-env NEXT_PUBLIC_URL="$VERCEL_PROJECT_PRODUCTION_URL" \ | |
| --build-env ICON= \ | |
| --build-env LOGO=gutenberg.jpg \ | |
| --build-env GITHUB="https://github.com/${{ github.repository }}" \ | |
| --build-env DISCORD="${{ secrets.DISCORD }}" \ | |
| --build-env THEME_PRIMARY="#323e48" \ | |
| --build-env THEME_SCHEME="tonalSpot" \ | |
| --build-env THEME_CONTRAST="0" \ | |
| --build-env THEME_NOTE="#1f6feb" \ | |
| --build-env THEME_TIP="#238636" \ | |
| --build-env THEME_IMPORTANT="#8957e5" \ | |
| --build-env THEME_WARNING="#d29922" \ | |
| --build-env THEME_CAUTION="#da3633" \ | |
| --build-env CONTRIBUTORS_PAT="${{ secrets.GITHUB_TOKEN }}" \ | |
| > deployment-url.txt | |
| echo "deployment_url=$(cat deployment-url.txt)" >> $GITHUB_OUTPUT | |
| env: | |
| VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} | |
| VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} | |
| # https://docs.github.com/en/actions/publishing-packages/publishing-docker-images#publishing-images-to-github-packages | |
| podman-job: | |
| runs-on: ubuntu-latest | |
| needs: release-job | |
| # Run if release-job was skipped (PRs) or if it completed with no changesets | |
| # On PRs: Build only to validate container configuration | |
| # On main: Build and push to registry | |
| if: | | |
| always() && | |
| (needs.release-job.result == 'skipped' || needs.release-job.outputs.hasChangesets == 'false') | |
| permissions: | |
| contents: write | |
| packages: write | |
| attestations: write | |
| id-token: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Get version from package.json | |
| id: get-version | |
| run: | | |
| VERSION=$(jq -r '.version' package.json) | |
| MAJOR_VERSION=$(echo "$VERSION" | cut -d. -f1) | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "major_version=$MAJOR_VERSION" >> $GITHUB_OUTPUT | |
| echo "Using version: $VERSION (major: $MAJOR_VERSION)" | |
| - name: Install Podman | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get -y install podman | |
| - name: Log in to the Container registry | |
| # Only login on main pushes since PRs don't push to registry | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: | | |
| echo "${{ secrets.GITHUB_TOKEN }}" | podman login ${{ env.REGISTRY }} -u ${{ github.actor }} --password-stdin | |
| - name: Build container image | |
| id: build | |
| run: | | |
| VERSION=${{ steps.get-version.outputs.version }} | |
| MAJOR_VERSION=${{ steps.get-version.outputs.major_version }} | |
| # Build the image | |
| podman build -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \ | |
| -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$VERSION \ | |
| -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$MAJOR_VERSION \ | |
| -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main \ | |
| --label "org.opencontainers.image.source=https://github.com/${{ github.repository }}" \ | |
| --label "org.opencontainers.image.revision=${{ github.sha }}" \ | |
| --label "org.opencontainers.image.version=$VERSION" \ | |
| . | |
| - name: Push container image | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: | | |
| VERSION=${{ steps.get-version.outputs.version }} | |
| MAJOR_VERSION=${{ steps.get-version.outputs.major_version }} | |
| podman push --digestfile /tmp/digest.txt ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest | |
| podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$VERSION | |
| podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$MAJOR_VERSION | |
| podman push ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:main | |
| - name: Get image digest | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| id: get-digest | |
| run: | | |
| # Get the digest from the pushed image | |
| DIGEST=$(cat /tmp/digest.txt) | |
| echo "digest=$DIGEST" >> $GITHUB_OUTPUT | |
| - name: Generate artifact attestation | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| uses: actions/attest-build-provenance@v3 | |
| with: | |
| subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| subject-digest: ${{ steps.get-digest.outputs.digest }} | |
| push-to-registry: true | |
| - name: Update `vX` git tag | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| run: | | |
| git config --global user.email "${{ github.actor }}@users.noreply.github.com" | |
| git config --global user.name "${{ github.actor }}" | |
| MAJOR_VERSION=${{ steps.get-version.outputs.major_version }} | |
| git tag -fa v$MAJOR_VERSION -m "Update major version tag to v$MAJOR_VERSION" | |
| git push origin v$MAJOR_VERSION --force |