1
0
forked from baron/baron-sso
Files
baron-sso/.gitea/workflows/image_publish.yml
2026-06-19 13:16:20 +09:00

242 lines
10 KiB
YAML

name: Publish Baron SSO Images
on:
workflow_dispatch:
inputs:
version_prefix:
description: "stage/prod 공용 이미지 태그 prefix (예: v1.2606, 최종 태그는 v1.2606.<커밋해시4자리>)"
required: true
type: string
jobs:
publish-images:
runs-on: ubuntu-latest
steps:
- name: Checkout dev branch
uses: actions/checkout@v4
with:
ref: dev
- name: Validate publish inputs
env:
VERSION_PREFIX: ${{ github.event.inputs.version_prefix }}
ADMINFRONT_URL: ${{ vars.ADMINFRONT_URL }}
DEVFRONT_URL: ${{ vars.DEVFRONT_URL }}
ORGFRONT_URL: ${{ vars.ORGFRONT_URL }}
VITE_OIDC_AUTHORITY: ${{ vars.VITE_OIDC_AUTHORITY }}
WORKS_DRIVE_SHARED_DRIVE_ID: ${{ vars.WORKS_DRIVE_SHARED_DRIVE_ID }}
WORKS_DRIVE_ACCESS_TOKEN_INPUT: ${{ secrets.WORKS_DRIVE_ACCESS_TOKEN }}
WORKS_DRIVE_ACCESS_TOKEN_FILE: ${{ vars.WORKS_DRIVE_ACCESS_TOKEN_FILE }}
WORKS_DRIVE_ACCESS_TOKEN_CMD: ${{ vars.WORKS_DRIVE_ACCESS_TOKEN_CMD }}
WORKS_DRIVE_OAUTH_CLIENT_ID: ${{ secrets.WORKS_DRIVE_OAUTH_CLIENT_ID }}
WORKS_DRIVE_OAUTH_CLIENT_SECRET: ${{ secrets.WORKS_DRIVE_OAUTH_CLIENT_SECRET }}
WORKS_DRIVE_OAUTH_REFRESH_TOKEN: ${{ secrets.WORKS_DRIVE_OAUTH_REFRESH_TOKEN }}
run: |
set -euo pipefail
if ! printf '%s' "${VERSION_PREFIX}" | grep -Eq '^v[0-9]+\.[0-9]{4}$'; then
echo "::error::version_prefix must look like vX.YYMM (got: ${VERSION_PREFIX})"
exit 1
fi
required_values="
ADMINFRONT_URL DEVFRONT_URL ORGFRONT_URL VITE_OIDC_AUTHORITY WORKS_DRIVE_SHARED_DRIVE_ID
"
for key in ${required_values}; do
if [ -z "${!key:-}" ]; then
echo "::error::Missing required publish value: ${key}. Check Gitea repo variables/secrets."
exit 1
fi
done
if [ -z "${WORKS_DRIVE_ACCESS_TOKEN_INPUT:-}" ] \
&& [ -z "${WORKS_DRIVE_ACCESS_TOKEN_FILE:-}" ] \
&& [ -z "${WORKS_DRIVE_ACCESS_TOKEN_CMD:-}" ] \
&& [ -z "${WORKS_DRIVE_OAUTH_REFRESH_TOKEN:-}" ]; then
echo "::error::Missing WORKS Drive access auth. Provide WORKS_DRIVE_ACCESS_TOKEN, WORKS_DRIVE_ACCESS_TOKEN_FILE, WORKS_DRIVE_ACCESS_TOKEN_CMD, or WORKS_DRIVE_OAUTH_REFRESH_TOKEN."
exit 1
fi
if [ -z "${WORKS_DRIVE_ACCESS_TOKEN_INPUT:-}" ] \
&& [ -z "${WORKS_DRIVE_ACCESS_TOKEN_FILE:-}" ] \
&& [ -z "${WORKS_DRIVE_ACCESS_TOKEN_CMD:-}" ] \
&& [ -n "${WORKS_DRIVE_OAUTH_REFRESH_TOKEN:-}" ] \
&& { [ -z "${WORKS_DRIVE_OAUTH_CLIENT_ID:-}" ] || [ -z "${WORKS_DRIVE_OAUTH_CLIENT_SECRET:-}" ]; }; then
echo "::error::WORKS_DRIVE_OAUTH_CLIENT_ID and WORKS_DRIVE_OAUTH_CLIENT_SECRET are required when WORKS_DRIVE_OAUTH_REFRESH_TOKEN is the selected auth source."
exit 1
fi
- name: Compute commit-hash image tag
id: version
env:
VERSION_PREFIX: ${{ github.event.inputs.version_prefix }}
run: |
set -euo pipefail
short_sha="$(git rev-parse --short=4 HEAD)"
if ! printf '%s' "${short_sha}" | grep -Eq '^[0-9a-f]{4}$'; then
echo "::error::commit hash suffix must be 4 lowercase hexadecimal characters (got: ${short_sha})"
exit 1
fi
image_tag="${VERSION_PREFIX}.${short_sha}"
echo "image_tag=${image_tag}" >> "${GITHUB_OUTPUT}"
echo "Computed shared image tag: ${image_tag}"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build backend image
uses: docker/build-push-action@v5
with:
context: ./backend
file: ./backend/Dockerfile
load: true
tags: baron_sso/backend:${{ steps.version.outputs.image_tag }}
provenance: false
sbom: false
- name: Build userfront image
uses: docker/build-push-action@v5
with:
context: .
file: ./userfront/Dockerfile
target: production
load: true
tags: baron_sso/userfront:${{ steps.version.outputs.image_tag }}
provenance: false
sbom: false
- name: Build adminfront image
uses: docker/build-push-action@v5
with:
context: .
file: ./adminfront/Dockerfile
target: production
load: true
tags: baron_sso/adminfront:${{ steps.version.outputs.image_tag }}
build-args: |
VITE_ADMIN_PUBLIC_URL=${{ vars.ADMINFRONT_URL }}
VITE_OIDC_AUTHORITY=${{ vars.VITE_OIDC_AUTHORITY }}
VITE_OIDC_CLIENT_ID=adminfront
ORGFRONT_URL=${{ vars.ORGFRONT_URL }}
provenance: false
sbom: false
- name: Build devfront image
uses: docker/build-push-action@v5
with:
context: .
file: ./devfront/Dockerfile
target: production
load: true
tags: baron_sso/devfront:${{ steps.version.outputs.image_tag }}
build-args: |
VITE_DEVFRONT_PUBLIC_URL=${{ vars.DEVFRONT_URL }}
VITE_OIDC_AUTHORITY=${{ vars.VITE_OIDC_AUTHORITY }}
VITE_OIDC_CLIENT_ID=devfront
ORGFRONT_URL=${{ vars.ORGFRONT_URL }}
provenance: false
sbom: false
- name: Build orgfront image
uses: docker/build-push-action@v5
with:
context: .
file: ./orgfront/Dockerfile
target: production
load: true
tags: baron_sso/orgfront:${{ steps.version.outputs.image_tag }}
build-args: |
VITE_ORGFRONT_PUBLIC_URL=${{ vars.ORGFRONT_URL }}
VITE_OIDC_AUTHORITY=${{ vars.VITE_OIDC_AUTHORITY }}
VITE_OIDC_CLIENT_ID=orgfront
provenance: false
sbom: false
- name: Resolve WORKS Drive access token
env:
WORKS_DRIVE_ACCESS_TOKEN_INPUT: ${{ secrets.WORKS_DRIVE_ACCESS_TOKEN }}
WORKS_DRIVE_ACCESS_TOKEN_FILE: ${{ vars.WORKS_DRIVE_ACCESS_TOKEN_FILE }}
WORKS_DRIVE_ACCESS_TOKEN_CMD: ${{ vars.WORKS_DRIVE_ACCESS_TOKEN_CMD }}
WORKS_DRIVE_OAUTH_CLIENT_ID: ${{ secrets.WORKS_DRIVE_OAUTH_CLIENT_ID }}
WORKS_DRIVE_OAUTH_CLIENT_SECRET: ${{ secrets.WORKS_DRIVE_OAUTH_CLIENT_SECRET }}
WORKS_DRIVE_OAUTH_REFRESH_TOKEN: ${{ secrets.WORKS_DRIVE_OAUTH_REFRESH_TOKEN }}
WORKS_ADMIN_OAUTH_TOKEN_URL: ${{ vars.WORKS_ADMIN_OAUTH_TOKEN_URL }}
run: |
set -euo pipefail
access_token=""
rotated_refresh_token_file="${RUNNER_TEMP}/works-drive-rotated-refresh-token"
if [ -n "${WORKS_DRIVE_ACCESS_TOKEN_INPUT:-}" ]; then
access_token="${WORKS_DRIVE_ACCESS_TOKEN_INPUT}"
elif [ -n "${WORKS_DRIVE_ACCESS_TOKEN_FILE:-}" ]; then
access_token="$(sed -n '1p' "${WORKS_DRIVE_ACCESS_TOKEN_FILE}")"
elif [ -n "${WORKS_DRIVE_ACCESS_TOKEN_CMD:-}" ]; then
access_token="$(sh -c "${WORKS_DRIVE_ACCESS_TOKEN_CMD}")"
else
token_url="${WORKS_ADMIN_OAUTH_TOKEN_URL:-https://auth.worksmobile.com/oauth2/v2.0/token}"
response="$(curl -sS -w $'\n%{http_code}' -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=refresh_token" \
--data-urlencode "refresh_token=${WORKS_DRIVE_OAUTH_REFRESH_TOKEN}" \
--data-urlencode "client_id=${WORKS_DRIVE_OAUTH_CLIENT_ID}" \
--data-urlencode "client_secret=${WORKS_DRIVE_OAUTH_CLIENT_SECRET}" \
"${token_url}")"
http_status="$(tail -n 1 <<<"${response}")"
response_body="$(sed '$d' <<<"${response}")"
if [ "${http_status}" -lt 200 ] || [ "${http_status}" -ge 300 ]; then
echo "::error::WORKS Drive access token refresh failed with HTTP ${http_status}."
exit 1
fi
access_token="$(jq -er '.access_token' <<<"${response_body}")"
rotated_refresh_token="$(jq -r '.refresh_token // empty' <<<"${response_body}")"
if [ -n "${rotated_refresh_token}" ]; then
echo "::add-mask::${rotated_refresh_token}"
printf '%s\n' "${rotated_refresh_token}" >"${rotated_refresh_token_file}"
chmod 600 "${rotated_refresh_token_file}"
echo "WORKS_DRIVE_ROTATED_REFRESH_TOKEN_FILE=${rotated_refresh_token_file}" >>"${GITHUB_ENV}"
echo "::warning::WORKS returned a rotated refresh token. Persist it to the WORKS_DRIVE_OAUTH_REFRESH_TOKEN secret before old refresh tokens age out."
fi
fi
if [ -z "${access_token}" ]; then
echo "::error::WORKS Drive access token could not be resolved."
exit 1
fi
echo "::add-mask::${access_token}"
echo "WORKS_DRIVE_ACCESS_TOKEN=${access_token}" >>"${GITHUB_ENV}"
- name: Upload built images to WORKS Drive archive
env:
IMAGE_TAG: ${{ steps.version.outputs.image_tag }}
WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR: ${{ vars.WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR }}
WORKS_DRIVE_TARGET: sharedrive
WORKS_DRIVE_SHARED_DRIVE_ID: ${{ vars.WORKS_DRIVE_SHARED_DRIVE_ID }}
WORKS_DRIVE_PARENT_FILE_ID: ${{ vars.WORKS_DRIVE_PARENT_FILE_ID }}
WORKS_ADMIN_API_BASE_URL: ${{ vars.WORKS_ADMIN_API_BASE_URL }}
run: |
set -euo pipefail
: "${WORKS_SHAREDRIVE_DOCKER_IMAGE_DIR:=docker-build-image}"
required_values="
IMAGE_TAG WORKS_DRIVE_SHARED_DRIVE_ID
"
for key in ${required_values}; do
if [ -z "${!key:-}" ]; then
echo "::error::Missing required WORKS image archive value: ${key}."
exit 1
fi
done
for image in backend userfront adminfront devfront orgfront; do
image_ref="baron_sso/${image}:${IMAGE_TAG}"
DOCKER_IMAGE_REF="${image_ref}" \
WORKS_DOCKER_IMAGE_ARCHIVE_DIR="${RUNNER_TEMP}/baron-sso-docker-image-upload" \
scripts/docker-image/upload_works_drive.sh
done