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}"