Bump version to 1.3.37 #83
Workflow file for this run
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: Build and Push Docker Image | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| env: | |
| IMAGE_NAME: ghcr.io/${{ github.repository }} | |
| concurrency: | |
| group: docker-publish-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.runner }} | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| matrix: | |
| include: | |
| - platform: linux/amd64 | |
| runner: ubuntu-latest | |
| - platform: linux/arm64 | |
| runner: ubuntu-24.04-arm | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata (tags, labels) | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=raw,value=latest | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| - name: Build and push by digest | |
| id: build | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| target: runtime | |
| platforms: ${{ matrix.platform }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true | |
| cache-from: type=gha,scope=${{ matrix.platform }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.platform }} | |
| - name: Export digest | |
| run: | | |
| mkdir -p /tmp/digests | |
| digest="${{ steps.build.outputs.digest }}" | |
| touch "/tmp/digests/${digest#sha256:}" | |
| - name: Upload digest | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: digests-${{ matrix.runner }} | |
| path: /tmp/digests/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| merge: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Download digests | |
| uses: actions/download-artifact@v4 | |
| with: | |
| path: /tmp/digests | |
| pattern: digests-* | |
| merge-multiple: true | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata (tags, labels) | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=raw,value=latest | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| - name: Create manifest list and push | |
| working-directory: /tmp/digests | |
| run: | | |
| docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ | |
| $(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *) | |
| cleanup: | |
| name: Cleanup old runs and artifacts | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| needs: merge | |
| permissions: | |
| actions: write | |
| steps: | |
| - name: Cleanup old workflow runs and artifacts | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const keepCount = 5; | |
| const { owner, repo } = context.repo; | |
| core.info('Fetching workflow runs...'); | |
| const runs = await github.paginate( | |
| github.rest.actions.listWorkflowRunsForRepo, | |
| { owner, repo, per_page: 100 } | |
| ); | |
| const sortedRuns = runs.sort((a, b) => | |
| new Date(b.created_at) - new Date(a.created_at) | |
| ); | |
| const runsToDelete = sortedRuns.slice(keepCount); | |
| core.info(`Found ${runs.length} workflow runs, deleting ${runsToDelete.length} older runs...`); | |
| for (const run of runsToDelete) { | |
| try { | |
| await github.rest.actions.deleteWorkflowRun({ owner, repo, run_id: run.id }); | |
| } catch (error) { | |
| core.warning(`Failed to delete run ${run.id}: ${error.message}`); | |
| } | |
| } | |
| core.info('Fetching artifacts...'); | |
| const artifacts = await github.paginate( | |
| github.rest.actions.listArtifactsForRepo, | |
| { owner, repo, per_page: 100 } | |
| ); | |
| const sortedArtifacts = artifacts | |
| .filter(artifact => !artifact.expired) | |
| .sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); | |
| const artifactsToDelete = sortedArtifacts.slice(keepCount); | |
| core.info(`Found ${artifacts.length} artifacts, deleting ${artifactsToDelete.length} older artifacts...`); | |
| for (const artifact of artifactsToDelete) { | |
| try { | |
| await github.rest.actions.deleteArtifact({ owner, repo, artifact_id: artifact.id }); | |
| } catch (error) { | |
| core.warning(`Failed to delete artifact ${artifact.id}: ${error.message}`); | |
| } | |
| } | |
| cleanup-ghcr: | |
| name: Cleanup old GHCR images | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| needs: merge | |
| permissions: | |
| packages: write | |
| steps: | |
| - name: Delete untagged and old images | |
| uses: actions/github-script@v7 | |
| with: | |
| github-token: ${{ secrets.RELEASES_TOKEN || secrets.GITHUB_TOKEN }} | |
| script: | | |
| const keepCount = 5; | |
| const { owner, repo } = context.repo; | |
| const packageName = repo.toLowerCase(); | |
| try { | |
| const ownerInfo = await github.rest.users.getByUsername({ username: owner }); | |
| const isOrg = ownerInfo.data.type === 'Organization'; | |
| const ownerArgs = isOrg ? { org: owner } : { username: owner }; | |
| const listVersions = isOrg | |
| ? github.rest.packages.getAllPackageVersionsForPackageOwnedByOrg | |
| : github.rest.packages.getAllPackageVersionsForPackageOwnedByUser; | |
| const deleteVersion = isOrg | |
| ? github.rest.packages.deletePackageVersionForOrg | |
| : github.rest.packages.deletePackageVersionForUser; | |
| const versions = await github.paginate( | |
| listVersions, | |
| { | |
| package_type: 'container', | |
| package_name: packageName, | |
| per_page: 100, | |
| state: 'active', | |
| ...ownerArgs, | |
| } | |
| ); | |
| const taggedVersions = versions.filter(v => v.metadata?.container?.tags?.length > 0); | |
| const untaggedVersions = versions.filter(v => !v.metadata?.container?.tags || v.metadata.container.tags.length === 0); | |
| const sortedTagged = taggedVersions.sort((a, b) => | |
| new Date(b.created_at) - new Date(a.created_at) | |
| ); | |
| const taggedToDelete = sortedTagged.slice(keepCount); | |
| const oldestKept = sortedTagged.length > 0 | |
| ? new Date(sortedTagged[Math.min(keepCount, sortedTagged.length) - 1].created_at) | |
| : new Date(); | |
| const untaggedToDelete = untaggedVersions.filter(v => | |
| new Date(v.created_at) < oldestKept | |
| ); | |
| for (const version of untaggedToDelete) { | |
| try { | |
| await deleteVersion({ | |
| package_type: 'container', | |
| package_name: packageName, | |
| package_version_id: version.id, | |
| ...ownerArgs, | |
| }); | |
| } catch (error) { | |
| core.warning(`Failed to delete untagged version ${version.id}: ${error.message}`); | |
| } | |
| } | |
| for (const version of taggedToDelete) { | |
| try { | |
| await deleteVersion({ | |
| package_type: 'container', | |
| package_name: packageName, | |
| package_version_id: version.id, | |
| ...ownerArgs, | |
| }); | |
| } catch (error) { | |
| core.warning(`Failed to delete tagged version ${version.id}: ${error.message}`); | |
| } | |
| } | |
| } catch (error) { | |
| if (error.status === 404) { | |
| core.info('No package found; skipping GHCR cleanup.'); | |
| } else { | |
| core.setFailed(`Error managing package versions: ${error.message}`); | |
| } | |
| } |