Files
ModelForge/.gitea/workflows/unraid-deploy.yml
T

133 lines
4.7 KiB
YAML

name: Unraid stable release deployment
on:
workflow_dispatch:
inputs:
release_tag:
description: Annotated stable release tag (for example, v1.2.1)
required: true
type: string
release_commit:
description: Exact lowercase 40-character commit SHA referenced by the tag
required: true
type: string
action:
description: Verify provenance only, or deploy the verified stable release
required: true
default: VERIFY_ONLY
type: choice
options:
- VERIFY_ONLY
- DEPLOY_STABLE_TO_PRODUCTION
concurrency:
group: unraid-production-itworx-modelforge
cancel-in-progress: false
permissions:
contents: read
jobs:
deploy:
name: Verify and optionally deploy a stable release
runs-on: unraid-deploy
timeout-minutes: 180
steps:
- name: Validate immutable dispatch inputs
shell: bash
env:
RELEASE_TAG: ${{ inputs.release_tag }}
RELEASE_COMMIT: ${{ inputs.release_commit }}
DEPLOY_ACTION: ${{ inputs.action }}
run: |
set -euo pipefail
if [[ "${GITHUB_REF:-}" != "refs/heads/master" ]]; then
echo "Stable production deployment must be dispatched from refs/heads/master" >&2
exit 2
fi
if [[ ! "${RELEASE_TAG}" =~ ^v(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]]; then
echo "release_tag must be a strict stable SemVer tag such as v1.2.1" >&2
exit 2
fi
if [[ ! "${RELEASE_COMMIT}" =~ ^[0-9a-f]{40}$ ]]; then
echo "release_commit must be an exact lowercase 40-character SHA" >&2
exit 2
fi
case "${DEPLOY_ACTION}" in
VERIFY_ONLY|DEPLOY_STABLE_TO_PRODUCTION) ;;
*) echo "action is not allowlisted: ${DEPLOY_ACTION}" >&2; exit 2 ;;
esac
- name: Check out the exact release commit with full history
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.release_commit }}
fetch-depth: 0
# The following provenance step performs an authenticated exact-ref fetch.
persist-credentials: true
- name: Verify stable release provenance
shell: bash
env:
RELEASE_TAG: ${{ inputs.release_tag }}
RELEASE_COMMIT: ${{ inputs.release_commit }}
run: |
set -euo pipefail
git fetch --force --no-recurse-submodules origin \
"refs/tags/${RELEASE_TAG}:refs/tags/${RELEASE_TAG}" \
"refs/heads/master:refs/remotes/origin/master"
tag_ref="refs/tags/${RELEASE_TAG}"
if [[ "$(git cat-file -t "${tag_ref}")" != "tag" ]]; then
echo "${RELEASE_TAG} must be an annotated tag" >&2
exit 1
fi
tag_object="$(git rev-parse "${tag_ref}^{tag}")"
tag_commit="$(git rev-parse "${tag_ref}^{commit}")"
head_commit="$(git rev-parse HEAD)"
if [[ "${tag_commit}" != "${RELEASE_COMMIT}" ]]; then
echo "Tag commit ${tag_commit} does not match release_commit ${RELEASE_COMMIT}" >&2
exit 1
fi
if [[ "${head_commit}" != "${RELEASE_COMMIT}" ]]; then
echo "Checked-out HEAD ${head_commit} does not match release_commit ${RELEASE_COMMIT}" >&2
exit 1
fi
if [[ ! -f VERSION ]]; then
echo "VERSION is missing at the release commit" >&2
exit 1
fi
version="$(tr -d '\r\n' < VERSION)"
expected_version="${RELEASE_TAG#v}"
if [[ "${version}" != "${expected_version}" ]]; then
echo "VERSION ${version} does not match release tag ${RELEASE_TAG}" >&2
exit 1
fi
if ! git merge-base --is-ancestor "${RELEASE_COMMIT}" refs/remotes/origin/master; then
echo "Release commit ${RELEASE_COMMIT} is not an ancestor of origin/master" >&2
exit 1
fi
printf 'DEPLOY_COMMIT=%s\n' "${RELEASE_COMMIT}" >> "${GITHUB_ENV}"
echo "Verified annotated ${RELEASE_TAG} object ${tag_object} at immutable commit ${RELEASE_COMMIT}"
- name: Verification-only result
if: ${{ inputs.action == 'VERIFY_ONLY' }}
shell: bash
run: echo "Stable release provenance verified; production was not changed."
- name: Deploy verified stable release to production
if: ${{ inputs.action == 'DEPLOY_STABLE_TO_PRODUCTION' }}
shell: bash
run: |
set -euo pipefail
test -n "${DEPLOY_COMMIT:-}"
docker exec gitea-deploy-control \
/opt/gitea-deploy/deploy.py deploy \
"${GITHUB_REPOSITORY}" "${DEPLOY_COMMIT}"