1919 url_prod :
2020 required : false
2121 type : string
22- default : nginx.org/preview
22+ default : nginx.org
2323 url_staging :
2424 required : false
2525 type : string
26- default : nginx.org/previews
27-
26+ default : staging.nginx.org
27+ s3_bucket :
28+ required : false
29+ type : string
30+ default : nginx-org-staging
31+ aws_region :
32+ required : false
33+ type : string
34+ default : eu-central-1
35+
2836permissions :
2937 contents : read
3038 id-token : write
@@ -34,11 +42,12 @@ defaults:
3442 shell : ' bash -Eeo pipefail -x {0}'
3543
3644jobs :
37- build :
38- name : build
45+ build-staging :
46+ name : build-staging
3947 runs-on : ubuntu-latest
40- env :
41- AWS_REGION : eu-central-1
48+ if : ${{ inputs.deployment_env == 'staging' }}
49+ environment :
50+ name : staging
4251
4352 steps :
4453 - name : Install dependencies
@@ -49,56 +58,14 @@ jobs:
4958 - name : Checkout
5059 uses : actions/checkout@v4
5160
52- - name : Check prod access
53- if : ${{ inputs.deployment_env == 'prod' }}
54- run : |
55- if [ "$GITHUB_REF" != "refs/heads/main" ]; then
56- echo "Error: Production deployments are only allowed from the main branch."
57- exit 1
58- fi
59-
60- if [ "$GITHUB_REPOSITORY_OWNER" != "nginx" ] && [ "$GITHUB_REPOSITORY_OWNER" != "nginxinc" ]; then
61- echo "Error: This workflow is only allowed in repositories owned by 'nginx' or 'nginxinc'."
62- exit 1
63- fi
64-
65- ALLOWED="${{ secrets.ALLOWED_USERS }}"
66- for user in $ALLOWED; do
67- if [ "$GITHUB_ACTOR" == "$user" ]; then
68- echo "User $GITHUB_ACTOR is allowed to deploy to prod"
69- exit 0
70- fi
71- done
72-
73- echo "User $GITHUB_ACTOR is NOT allowed to deploy to prod"
74- exit 1
75-
7661 - name : Configure AWS credentials
7762 uses : aws-actions/configure-aws-credentials@v4
7863 with :
79- role-to-assume : arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ inputs.deployment_env == 'prod' && secrets.AWS_ROLE_NAME_PROD || secrets.AWS_ROLE_NAME_STAGING }}
80- aws-region : ${{ env.AWS_REGION }}
81-
82- - name : Determine S3 path
83- id : s3path
84- run : |
85- SAFE_REPO="${GITHUB_REPOSITORY//\//-}"
86- if [[ "${{ inputs.deployment_env }}" == "prod" ]]; then
87- BUCKET="nginx-org-prod"
88- PATH_PART="preview"
89- PUBLIC_URL="${{ inputs.url_prod }}"
90- else
91- BUCKET="nginx-org-staging"
92- PATH_PART="previews/${GITHUB_SHA}"
93- PUBLIC_URL="${{ inputs.url_staging }}/${GITHUB_SHA}/"
94- fi
95- echo "bucket=$BUCKET" >> $GITHUB_OUTPUT
96- echo "path=$PATH_PART" >> $GITHUB_OUTPUT
97- echo "s3_uri=s3://$BUCKET/$SAFE_REPO/$PATH_PART/" >> $GITHUB_OUTPUT
98- echo "public_url=$PUBLIC_URL" >> $GITHUB_OUTPUT
99- echo "safe_repo=$SAFE_REPO" >> $GITHUB_OUTPUT
64+ role-to-assume : arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME_STAGING }}
65+ aws-region : ${{ inputs.aws_region }}
10066
101- - name : Build site
67+ - name : Build
68+ if : ${{ inputs.deployment_env == 'staging' }}
10269 run : |
10370 set -e
10471 make all
@@ -113,40 +80,98 @@ jobs:
11380 echo "Error: Build did not create www/ directory"
11481 exit 1
11582 fi
116-
83+
11784 - name : Add deployment metadata
85+ if : ${{ inputs.deployment_env == 'staging' }}
11886 run : |
11987 TIMESTAMP="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
12088 mkdir -p meta
12189 echo "$GITHUB_SHA deployed at $TIMESTAMP" > meta/.deployed.txt
122- {
123- echo "sha=$GITHUB_SHA"
124- echo "repo=$GITHUB_REPOSITORY"
125- echo "actor=$GITHUB_ACTOR"
126- echo "timestamp=$TIMESTAMP"
127- } > meta/.tags.txt
90+ echo "actor=$GITHUB_ACTOR repo=$GITHUB_REPOSITORY" >> meta/.deployed.txt
12891 cp meta/.deployed.txt www/
129- cp meta/.tags.txt www/
130-
92+
13193 - name : Sync www/ to S3
13294 run : |
133- aws s3 sync www/ s3://${{ steps.s3path.outputs.bucket }}/${{ steps.s3path.outputs.safe_repo }}/${{ steps.s3path.outputs.path }}/ --delete --exact-timestamps
95+ aws s3 sync \
96+ www/ \
97+ s3://${{ inputs.s3_bucket }}/${{ github.repository.replace('/', '-') }}/staging/${GITHUB_SHA}/ \
98+ --delete --exact-timestamps
13499
135- - name : Show uploaded files
100+ - name : Deployment summary
136101 run : |
137- aws s3 ls s3://${{ steps.s3path.outputs.bucket }}/${{ steps.s3path.outputs.safe_repo }}/${{ steps.s3path.outputs.path }}/ --recursive
102+ {
103+ echo "### Deployment staging to ${{ inputs.url_staging }}/${{ github.repository.replace('/', '-') }}/${GITHUB_SHA}"
104+ echo "### It should be accessible in 5 minutes"
105+ } >> $GITHUB_STEP_SUMMARY
106+
107+ build-prod :
108+ name : build-prod
109+ runs-on : ubuntu-latest
110+ if : ${{ inputs.deployment_env == 'prod' }}
111+ environment :
112+ name : prod
113+
114+ steps :
115+
116+ - name : Check prod access
117+ if : ${{ inputs.deployment_env == 'prod' }}
118+ run : |
119+ if [ "$GITHUB_REF" != "refs/heads/main" ]; then
120+ echo "Error: Production deployments are only allowed from the main branch."
121+ exit 1
122+ fi
138123
124+ if [ "$GITHUB_REPOSITORY_OWNER" != "nginx" ] && [ "$GITHUB_REPOSITORY_OWNER" != "nginxinc" ]; then
125+ echo "Error: This workflow is only allowed in repositories owned by 'nginx' or 'nginxinc'."
126+ exit 1
127+ fi
128+
129+ allowed=false
130+ USER_LIST="${{ secrets.ALLOWED_USERS }}"
131+ for user in $USER_LIST; do
132+ if [ "$GITHUB_ACTOR" == "$user" ]; then
133+ echo "User $GITHUB_ACTOR is allowed to deploy to prod"
134+ allowed=true
135+ break
136+ fi
137+ done
138+
139+ if [ "$allowed" != true ]; then
140+ echo "User $GITHUB_ACTOR is NOT allowed to deploy to prod"
141+ exit 1
142+ fi
143+
144+ - name : Configure AWS credentials
145+ uses : aws-actions/configure-aws-credentials@v4
146+ with :
147+ role-to-assume : arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME_STAGING }}
148+ aws-region : ${{ inputs.aws_region }}
149+
150+
151+ - name : Sync www/ to S3
152+ run : |
153+ aws s3 sync \
154+ s3://${{ inputs.s3_bucket }}/${{ github.repository.replace('/', '-') }}/staging/${GITHUB_SHA}/ \
155+ s3://${{ inputs.s3_bucket }}/${{ github.repository.replace('/', '-') }}/prod/ \
156+ --delete --exact-timestamps
157+
158+ - name : Check prod deployment
159+ run : |
160+ DEPLOYED_URL="${{ inputs.url_staging }}/${{ github.repository.replace('/', '-') }}/${GITHUB_SHA}/.deployed.txt"
161+ for i in {1..10}; do
162+ DEPLOYED_SHA=$(curl -fsSL "$DEPLOYED_URL" 2>/dev/null | awk '{ print $1 }' || echo "")
163+ if [ "$DEPLOYED_SHA" = "$GITHUB_SHA" ]; then
164+ exit 0
165+ else
166+ sleep 60
167+ fi
168+ done
169+
170+ echo "Error: wrong SHA while requesting $DEPLOYED_URL"
171+ exit 1
172+
139173 - name : Deployment summary
140174 run : |
141175 {
142- echo "### Deployment Summary"
143- echo ""
144- echo "| Key | Value |"
145- echo "|------------------|-------|"
146- echo "| deployment_env | ${{ inputs.deployment_env }} |"
147- echo "| repository | $GITHUB_REPOSITORY |"
148- echo "| actor | $GITHUB_ACTOR |"
149- echo "| commit | $GITHUB_SHA |"
150- echo "| S3 path | ${{ steps.s3path.outputs.s3_uri }} |"
151- echo "| Public URL | ${{ steps.s3path.outputs.public_url }} |"
176+ echo "### prod is deployed by $GITHUB_ACTOR from $GITHUB_REPOSITORY/$GITHUB_SHA"
152177 } >> $GITHUB_STEP_SUMMARY
0 commit comments