ci(release): promote SHA-tagged images on release
Publish branch builds under immutable commit SHA tags, then promote the released image to its version tag and stable releases to latest.
This commit is contained in:
parent
a92ca6e3b8
commit
7716e65eea
3 changed files with 149 additions and 40 deletions
48
.github/workflows/coolify-production-build.yml
vendored
48
.github/workflows/coolify-production-build.yml
vendored
|
|
@ -3,17 +3,6 @@ name: Production Build (v4)
|
|||
on:
|
||||
push:
|
||||
branches: ["v4.x"]
|
||||
paths-ignore:
|
||||
- .github/workflows/coolify-helper.yml
|
||||
- .github/workflows/coolify-helper-next.yml
|
||||
- .github/workflows/coolify-realtime.yml
|
||||
- .github/workflows/coolify-realtime-next.yml
|
||||
- .github/workflows/pr-quality.yaml
|
||||
- docker/coolify-helper/Dockerfile
|
||||
- docker/coolify-realtime/Dockerfile
|
||||
- docker/testing-host/Dockerfile
|
||||
- templates/**
|
||||
- CHANGELOG.md
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
|
@ -55,11 +44,6 @@ jobs:
|
|||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build and Push Image (${{ matrix.arch }})
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
|
|
@ -68,17 +52,13 @@ jobs:
|
|||
platforms: ${{ matrix.platform }}
|
||||
push: true
|
||||
tags: |
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
|
||||
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-${{ matrix.arch }}
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}-${{ matrix.arch }}
|
||||
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}-${{ matrix.arch }}
|
||||
|
||||
merge-manifest:
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build-push
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to ${{ env.GITHUB_REGISTRY }}
|
||||
|
|
@ -95,28 +75,16 @@ jobs:
|
|||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Get Version
|
||||
id: version
|
||||
run: |
|
||||
echo "VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)"|xargs >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create & publish manifest on ${{ env.GITHUB_REGISTRY }}
|
||||
run: |
|
||||
docker buildx imagetools create \
|
||||
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
|
||||
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
|
||||
--tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
|
||||
--tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}-amd64 \
|
||||
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}-aarch64 \
|
||||
--tag ${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}
|
||||
|
||||
- name: Create & publish manifest on ${{ env.DOCKER_REGISTRY }}
|
||||
run: |
|
||||
docker buildx imagetools create \
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-amd64 \
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }}-aarch64 \
|
||||
--tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.VERSION }} \
|
||||
--tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
||||
|
||||
- uses: sarisia/actions-status-discord@v1
|
||||
if: always()
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }}
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}-amd64 \
|
||||
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}-aarch64 \
|
||||
--tag ${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:sha-${{ github.sha }}
|
||||
|
|
|
|||
107
.github/workflows/coolify-release.yml
vendored
Normal file
107
.github/workflows/coolify-release.yml
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
name: Release Coolify
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
GITHUB_REGISTRY: ghcr.io
|
||||
DOCKER_REGISTRY: docker.io
|
||||
IMAGE_NAME: coollabsio/coolify
|
||||
|
||||
jobs:
|
||||
promote-image:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
ref: ${{ github.event.release.tag_name }}
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to ${{ env.GITHUB_REGISTRY }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.GITHUB_REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to ${{ env.DOCKER_REGISTRY }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.DOCKER_REGISTRY }}
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Resolve release image
|
||||
id: release
|
||||
env:
|
||||
TAG_NAME: ${{ github.event.release.tag_name }}
|
||||
run: |
|
||||
if [[ ! "${TAG_NAME}" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z.-]+)?$ ]]; then
|
||||
echo "Unsupported release tag: ${TAG_NAME}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
VERSION="${TAG_NAME#v}"
|
||||
RELEASE_SHA=$(git rev-list -n 1 "${TAG_NAME}")
|
||||
CONFIG_VERSION=$(docker run --rm -v "$(pwd):/app" -w /app php:8.2-alpine3.16 php bootstrap/getVersion.php)
|
||||
|
||||
if [[ "${CONFIG_VERSION}" != "${VERSION}" ]]; then
|
||||
echo "Release tag ${VERSION} does not match config version ${CONFIG_VERSION}."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
||||
echo "sha=${RELEASE_SHA}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Promote version on ${{ env.GITHUB_REGISTRY }}
|
||||
env:
|
||||
REGISTRY: ${{ env.GITHUB_REGISTRY }}
|
||||
VERSION: ${{ steps.release.outputs.version }}
|
||||
RELEASE_SHA: ${{ steps.release.outputs.sha }}
|
||||
run: |
|
||||
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
||||
SOURCE_TAG="sha-${RELEASE_SHA}"
|
||||
docker buildx imagetools create "${IMAGE}:${SOURCE_TAG}" --tag "${IMAGE}:${VERSION}"
|
||||
|
||||
- name: Promote version on ${{ env.DOCKER_REGISTRY }}
|
||||
env:
|
||||
REGISTRY: ${{ env.DOCKER_REGISTRY }}
|
||||
VERSION: ${{ steps.release.outputs.version }}
|
||||
RELEASE_SHA: ${{ steps.release.outputs.sha }}
|
||||
run: |
|
||||
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
||||
SOURCE_TAG="sha-${RELEASE_SHA}"
|
||||
docker buildx imagetools create "${IMAGE}:${SOURCE_TAG}" --tag "${IMAGE}:${VERSION}"
|
||||
|
||||
- name: Promote latest on ${{ env.GITHUB_REGISTRY }}
|
||||
if: ${{ ! github.event.release.prerelease }}
|
||||
env:
|
||||
REGISTRY: ${{ env.GITHUB_REGISTRY }}
|
||||
RELEASE_SHA: ${{ steps.release.outputs.sha }}
|
||||
run: |
|
||||
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
||||
SOURCE_TAG="sha-${RELEASE_SHA}"
|
||||
docker buildx imagetools create "${IMAGE}:${SOURCE_TAG}" --tag "${IMAGE}:latest"
|
||||
|
||||
- name: Promote latest on ${{ env.DOCKER_REGISTRY }}
|
||||
if: ${{ ! github.event.release.prerelease }}
|
||||
env:
|
||||
REGISTRY: ${{ env.DOCKER_REGISTRY }}
|
||||
RELEASE_SHA: ${{ steps.release.outputs.sha }}
|
||||
run: |
|
||||
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
||||
SOURCE_TAG="sha-${RELEASE_SHA}"
|
||||
docker buildx imagetools create "${IMAGE}:${SOURCE_TAG}" --tag "${IMAGE}:latest"
|
||||
|
||||
- uses: sarisia/actions-status-discord@v1
|
||||
if: always()
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }}
|
||||
34
tests/Unit/ProductionImageWorkflowTest.php
Normal file
34
tests/Unit/ProductionImageWorkflowTest.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
it('publishes v4 branch builds only under the commit sha', function () {
|
||||
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-production-build.yml');
|
||||
|
||||
expect($workflow)
|
||||
->toContain('sha-${{ github.sha }}-${{ matrix.arch }}')
|
||||
->toContain('sha-${{ github.sha }}')
|
||||
->not->toContain('bootstrap/getVersion.php')
|
||||
->not->toContain('steps.version.outputs.VERSION')
|
||||
->not->toContain('IMAGE_NAME }}:latest');
|
||||
});
|
||||
|
||||
it('promotes the released commit image without rebuilding it', function () {
|
||||
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-release.yml');
|
||||
|
||||
expect($workflow)
|
||||
->toContain('release:')
|
||||
->toContain('types: [published]')
|
||||
->toContain('TAG_NAME: ${{ github.event.release.tag_name }}')
|
||||
->toContain('git rev-list -n 1 "${TAG_NAME}"')
|
||||
->toContain('SOURCE_TAG="sha-${RELEASE_SHA}"')
|
||||
->toContain('bootstrap/getVersion.php')
|
||||
->toContain('--tag "${IMAGE}:${VERSION}"')
|
||||
->not->toContain('docker/build-push-action');
|
||||
});
|
||||
|
||||
it('only promotes stable releases to latest', function () {
|
||||
$workflow = file_get_contents(dirname(__DIR__, 2).'/.github/workflows/coolify-release.yml');
|
||||
|
||||
expect($workflow)
|
||||
->toContain('if: ${{ ! github.event.release.prerelease }}')
|
||||
->toContain('--tag "${IMAGE}:latest"');
|
||||
});
|
||||
Loading…
Reference in a new issue