add deployment marks and check them on prod deploy (#50) #4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: nginx.org build | ||
on: | ||
workflow_call: | ||
secrets: | ||
AWS_ACCOUNT_ID: | ||
required: true | ||
AWS_ROLE_NAME: | ||
required: true | ||
ALLOWED_USERS: | ||
required: true | ||
inputs: | ||
deployment_env: | ||
required: false | ||
type: string | ||
default: staging | ||
url_prod: | ||
required: false | ||
type: string | ||
default: nginx.org | ||
url_staging: | ||
required: false | ||
type: string | ||
default: staging.nginx.org | ||
s3_bucket: | ||
required: false | ||
type: string | ||
default: nginx-org-staging | ||
aws_region: | ||
required: false | ||
type: string | ||
default: eu-central-1 | ||
permissions: | ||
contents: read | ||
id-token: write | ||
defaults: | ||
run: | ||
shell: 'bash -Eeo pipefail -x {0}' | ||
jobs: | ||
check-if-allowed: | ||
if: ${{ ( github.repository_owner == 'nginx' || github.repository_owner == 'nginxinc' ) }} | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Check if we're in the allowed environment | ||
run: | | ||
org_found=0 | ||
event_found=0 | ||
ref_found=0 | ||
user_found=0 | ||
ALLOWED_ORGS="nginx nginxinc" | ||
ALLOWED_EVENTS="push workflow_dispatch" | ||
ALLOWED_REFS="refs/heads/main" | ||
ALLOWED_USERS="${{ secrets.ALLOWED_USERS }}" | ||
for org in $ALLOWED_ORGS; do | ||
if [ "$org" == "$GITHUB_REPOSITORY_OWNER" ]; then org_found=1; fi | ||
done | ||
for event in $ALLOWED_EVENTS; do | ||
if [ "$event" == "$GITHUB_EVENT_NAME" ]; then event_found=1; fi | ||
done | ||
for ref in $ALLOWED_REFS; do | ||
if [ ${{ inputs.deployment_env }} == 'prod' ]; then | ||
if [ "$ref" == "$GITHUB_REF" ]; then ref_found=1; fi | ||
else | ||
ref_found=1 | ||
fi | ||
done | ||
for user in $ALLOWED_USERS; do | ||
if [ ${{ inputs.deployment_env }} == 'prod' ]; then | ||
if [ "$user" == "$GITHUB_ACTOR" ]; then user_found=1; fi | ||
else | ||
user_found=1 | ||
fi | ||
done | ||
if [ $org_found$event_found$ref_found$user_found -ne 1111 ]; then | ||
echo "Repository owner, event, ref or actor are not explicitely allowed to use this workflow: $GITHUB_REPOSITORY_OWNER, $GITHUB_EVENT_NAME, $GITHUB_REF, $GITHUB_ACTOR" | ||
exit 1 | ||
fi | ||
exit 0 | ||
build-staging: | ||
name: build-staging | ||
runs-on: ubuntu-latest | ||
needs: check-if-allowed | ||
if: ${{ inputs.deployment_env == 'staging' }} | ||
steps: | ||
- name: Install dependencies | ||
run: | | ||
sudo apt-get update | ||
sudo apt-get install -y libxslt1-dev xsltproc libxml2-utils netpbm python-is-python3 | ||
- name: Checkout | ||
uses: actions/checkout@v4 | ||
- name: Configure AWS credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }} | ||
aws-region: ${{ inputs.aws_region }} | ||
- name: Build | ||
if: ${{ inputs.deployment_env == 'staging' }} | ||
run: | | ||
set -e | ||
make all | ||
make gzip | ||
make images | ||
make genapi | ||
make all | ||
make copy NGINX_ORG=www | ||
# Verify build output | ||
if [ ! -d www ]; then | ||
echo "Error: Build did not create www/ directory" | ||
exit 1 | ||
fi | ||
- name: Compute safe repo name | ||
id: vars | ||
run: | | ||
echo "safe_repo=${GITHUB_REPOSITORY//\//-}" >> "$GITHUB_OUTPUT" | ||
- name: Sync www/ to S3 | ||
run: | | ||
aws s3 sync \ | ||
www/ \ | ||
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/staging/${GITHUB_SHA}/ \ | ||
--delete --exact-timestamps | ||
- name: Upload staging markers (.deployed.txt) | ||
run: | | ||
TIMESTAMP="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" | ||
cat > .deployed.txt <<EOF | ||
sha=${GITHUB_SHA} | ||
env=staging | ||
ts=${TIMESTAMP} | ||
actor=${GITHUB_ACTOR} | ||
repo=${GITHUB_REPOSITORY} | ||
EOF | ||
aws s3 cp .deployed.txt \ | ||
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/staging/${GITHUB_SHA}/.deployed.txt | ||
aws s3 cp .deployed.txt \ | ||
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/staging/.deployed.txt | ||
- name: Deployment summary | ||
run: | | ||
{ | ||
echo "### Deployment Summary" | ||
echo "" | ||
echo "| Key | Value |" | ||
echo "|------------------|-------|" | ||
echo "| deployment_env | ${{ inputs.deployment_env }} |" | ||
echo "| repository | $GITHUB_REPOSITORY |" | ||
echo "| actor | $GITHUB_ACTOR |" | ||
echo "| commit | $GITHUB_SHA |" | ||
echo "| Public URL | https://${{ inputs.url_staging }}/${GITHUB_SHA} |" | ||
} >> $GITHUB_STEP_SUMMARY | ||
build-prod: | ||
name: build-prod | ||
runs-on: ubuntu-latest | ||
needs: check-if-allowed | ||
if: ${{ inputs.deployment_env == 'prod' }} | ||
steps: | ||
- name: Configure AWS credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | ||
with: | ||
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }} | ||
aws-region: ${{ inputs.aws_region }} | ||
- name: Compute safe repo name | ||
id: vars | ||
run: | | ||
echo "safe_repo=${GITHUB_REPOSITORY//\//-}" >> "$GITHUB_OUTPUT" | ||
- name: Wait for staging marker for this SHA | ||
run: | | ||
set -e | ||
S3="s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/staging/${GITHUB_SHA}/.deployed.txt" | ||
for i in $(seq 1 10); do | ||
if aws s3 cp "$S3" .staging.marker --only-show-errors; then | ||
grep -q '^sha=' .staging.marker && grep -q '^env=staging' .staging.marker && exit 0 || true | ||
fi | ||
sleep 10 | ||
done | ||
echo "staging marker not ready for ${GITHUB_SHA}" >&2 | ||
exit 1 | ||
- name: Sync www/ to S3 | ||
run: | | ||
aws s3 sync \ | ||
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/staging/${GITHUB_SHA}/ \ | ||
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/prod/ \ | ||
--delete --exact-timestamps | ||
- name: Upload prod marker (.deployed.txt) | ||
run: | | ||
TIMESTAMP="$(date -u +"%Y-%m-%dT%H:%M:%SZ")" | ||
cat > .deployed.txt <<EOF | ||
sha=${GITHUB_SHA} | ||
env=prod | ||
ts=${TIMESTAMP} | ||
actor=${GITHUB_ACTOR} | ||
repo=${GITHUB_REPOSITORY} | ||
EOF | ||
aws s3 cp .deployed.txt \ | ||
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/prod/.deployed.txt | ||
- name: Deployment summary | ||
run: | | ||
{ | ||
echo "### Deployment Summary" | ||
echo "" | ||
echo "| Key | Value |" | ||
echo "|------------------|-------|" | ||
echo "| deployment_env | ${{ inputs.deployment_env }} |" | ||
echo "| repository | $GITHUB_REPOSITORY |" | ||
echo "| actor | $GITHUB_ACTOR |" | ||
echo "| commit | $GITHUB_SHA |" | ||
echo "| Public URL | https://${{ inputs.url_prod }} |" | ||
} >> $GITHUB_STEP_SUMMARY |