mirror of
https://github.com/tiennm99/coolify.git
synced 2026-08-20 04:23:34 +00:00
260 lines
8.6 KiB
YAML
260 lines
8.6 KiB
YAML
name: Release Coolify Stable
|
|
run-name: ${{ inputs.tag }}
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
tag:
|
|
description: Existing draft release tag (for example, v4.3.1)
|
|
required: true
|
|
type: string
|
|
|
|
permissions: {}
|
|
|
|
concurrency:
|
|
group: coolify-fix-release
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
GITHUB_REGISTRY: ghcr.io
|
|
DOCKER_REGISTRY: docker.io
|
|
IMAGE_NAME: coollabsio/coolify
|
|
|
|
jobs:
|
|
validate:
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
contents: write
|
|
outputs:
|
|
release_id: ${{ steps.draft.outputs.release_id }}
|
|
version: ${{ steps.version.outputs.version }}
|
|
steps:
|
|
- name: Reject releases outside the production branch
|
|
if: ${{ github.ref_name != 'main' }}
|
|
run: |
|
|
echo "Stable releases must run from main, not ${{ github.ref_name }}."
|
|
exit 1
|
|
|
|
- uses: actions/checkout@v5
|
|
with:
|
|
fetch-depth: 0
|
|
persist-credentials: false
|
|
|
|
- name: Validate version
|
|
id: version
|
|
env:
|
|
TAG_NAME: ${{ inputs.tag }}
|
|
run: |
|
|
if [[ ! "${TAG_NAME}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
echo "Unsupported fix release tag: ${TAG_NAME}"
|
|
exit 1
|
|
fi
|
|
|
|
VERSION="${TAG_NAME#v}"
|
|
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"
|
|
|
|
- name: Validate and pin draft release
|
|
id: draft
|
|
uses: actions/github-script@v8
|
|
env:
|
|
TAG_NAME: ${{ inputs.tag }}
|
|
with:
|
|
script: |
|
|
const releases = await github.paginate(github.rest.repos.listReleases, {
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
per_page: 100,
|
|
});
|
|
const release = releases.find((candidate) => candidate.tag_name === process.env.TAG_NAME);
|
|
|
|
if (!release) {
|
|
core.setFailed(`Create a draft release for ${process.env.TAG_NAME} before running this workflow.`);
|
|
return;
|
|
}
|
|
if (!release.draft) {
|
|
core.setFailed(`Release ${process.env.TAG_NAME} must still be a draft.`);
|
|
return;
|
|
}
|
|
if (release.prerelease) {
|
|
core.setFailed(`Fix release ${process.env.TAG_NAME} cannot be marked as a prerelease.`);
|
|
return;
|
|
}
|
|
if (!release.body?.trim()) {
|
|
core.setFailed(`Draft release ${process.env.TAG_NAME} must contain reviewed release notes.`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await github.rest.git.getRef({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
ref: `tags/${process.env.TAG_NAME}`,
|
|
});
|
|
core.setFailed(`Git tag ${process.env.TAG_NAME} already exists.`);
|
|
return;
|
|
} catch (error) {
|
|
if (error.status !== 404) throw error;
|
|
}
|
|
|
|
await github.rest.repos.updateRelease({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
release_id: release.id,
|
|
tag_name: process.env.TAG_NAME,
|
|
target_commitish: context.sha,
|
|
});
|
|
core.setOutput('release_id', release.id);
|
|
|
|
build:
|
|
needs: validate
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
matrix:
|
|
include:
|
|
- arch: amd64
|
|
platform: linux/amd64
|
|
runner: ubuntu-24.04
|
|
- arch: aarch64
|
|
platform: linux/aarch64
|
|
runner: ubuntu-24.04-arm
|
|
runs-on: ${{ matrix.runner }}
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
with:
|
|
persist-credentials: false
|
|
|
|
- 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: Build and push release image (${{ matrix.arch }})
|
|
uses: docker/build-push-action@v6
|
|
with:
|
|
context: .
|
|
file: docker/production/Dockerfile
|
|
platforms: ${{ matrix.platform }}
|
|
push: true
|
|
build-args: |
|
|
COOLIFY_VERSION=${{ needs.validate.outputs.version }}
|
|
tags: |
|
|
${{ env.GITHUB_REGISTRY }}/${{ env.IMAGE_NAME }}:release-${{ needs.validate.outputs.version }}-${{ github.sha }}-${{ matrix.arch }}
|
|
${{ env.DOCKER_REGISTRY }}/${{ env.IMAGE_NAME }}:release-${{ needs.validate.outputs.version }}-${{ github.sha }}-${{ matrix.arch }}
|
|
|
|
publish:
|
|
needs: [validate, build]
|
|
runs-on: ubuntu-24.04
|
|
permissions:
|
|
contents: write
|
|
packages: write
|
|
steps:
|
|
- 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: Publish version and latest on ${{ env.GITHUB_REGISTRY }}
|
|
env:
|
|
REGISTRY: ${{ env.GITHUB_REGISTRY }}
|
|
VERSION: ${{ needs.validate.outputs.version }}
|
|
run: |
|
|
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
|
SOURCE="release-${VERSION}-${GITHUB_SHA}"
|
|
docker buildx imagetools create \
|
|
"${IMAGE}:${SOURCE}-amd64" \
|
|
"${IMAGE}:${SOURCE}-aarch64" \
|
|
--tag "${IMAGE}:${VERSION}" \
|
|
--tag "${IMAGE}:latest"
|
|
|
|
- name: Publish version and latest on ${{ env.DOCKER_REGISTRY }}
|
|
env:
|
|
REGISTRY: ${{ env.DOCKER_REGISTRY }}
|
|
VERSION: ${{ needs.validate.outputs.version }}
|
|
run: |
|
|
IMAGE="${REGISTRY}/${IMAGE_NAME}"
|
|
SOURCE="release-${VERSION}-${GITHUB_SHA}"
|
|
docker buildx imagetools create \
|
|
"${IMAGE}:${SOURCE}-amd64" \
|
|
"${IMAGE}:${SOURCE}-aarch64" \
|
|
--tag "${IMAGE}:${VERSION}" \
|
|
--tag "${IMAGE}:latest"
|
|
|
|
- name: Publish reviewed draft release
|
|
uses: actions/github-script@v8
|
|
env:
|
|
RELEASE_ID: ${{ needs.validate.outputs.release_id }}
|
|
TAG_NAME: ${{ inputs.tag }}
|
|
with:
|
|
script: |
|
|
const releaseId = Number(process.env.RELEASE_ID);
|
|
const { data: release } = await github.rest.repos.getRelease({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
release_id: releaseId,
|
|
});
|
|
|
|
if (release.tag_name !== process.env.TAG_NAME || !release.draft || release.prerelease) {
|
|
core.setFailed(`Draft release ${process.env.TAG_NAME} changed while the images were building.`);
|
|
return;
|
|
}
|
|
if (!release.body?.trim()) {
|
|
core.setFailed(`Draft release ${process.env.TAG_NAME} no longer contains release notes.`);
|
|
return;
|
|
}
|
|
if (release.target_commitish !== context.sha) {
|
|
core.setFailed(`Draft release ${process.env.TAG_NAME} no longer targets ${context.sha}.`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
await github.rest.git.getRef({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
ref: `tags/${process.env.TAG_NAME}`,
|
|
});
|
|
core.setFailed(`Git tag ${process.env.TAG_NAME} was created while the images were building.`);
|
|
return;
|
|
} catch (error) {
|
|
if (error.status !== 404) throw error;
|
|
}
|
|
|
|
await github.rest.repos.updateRelease({
|
|
owner: context.repo.owner,
|
|
repo: context.repo.repo,
|
|
release_id: Number(process.env.RELEASE_ID),
|
|
tag_name: process.env.TAG_NAME,
|
|
target_commitish: context.sha,
|
|
draft: false,
|
|
});
|