Skip to content

Commit 87da992

Browse files
authored
nginx.org deploy with az-sync (#61)
nginx.org deploy
1 parent 129ceed commit 87da992

File tree

3 files changed

+172
-23
lines changed

3 files changed

+172
-23
lines changed

.github/workflows/nginx.org-make-aws.yml

Lines changed: 85 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ name: nginx.org build
33
on:
44
workflow_call:
55
secrets:
6-
AWS_ACCOUNT_ID:
6+
AZURE_VAULT_CLIENT_ID:
77
required: true
8-
AWS_ROLE_NAME:
8+
AZURE_VAULT_SUBSCRIPTION_ID:
99
required: true
10-
ALLOWED_USERS:
10+
AZURE_VAULT_TENANT_ID:
11+
required: true
12+
DOCS_VAULTNAME:
1113
required: true
1214
inputs:
1315
deployment_env:
@@ -40,12 +42,26 @@ defaults:
4042
shell: 'bash -Eeo pipefail -x {0}'
4143

4244
jobs:
43-
check-if-allowed:
44-
if: ${{ ( github.repository_owner == 'nginx' || github.repository_owner == 'nginxinc' ) }}
45+
build-staging:
46+
name: build-staging
4547
runs-on: ubuntu-latest
48+
environment: preview
49+
if: ${{ inputs.deployment_env == 'staging' }}
4650

4751
steps:
52+
- name: Get Secrets from Azure Key Vault
53+
uses: nginxinc/docs-actions/.github/actions/az-sync@129ceed709adf17d9bfad75bd31a6ec0dbf1cd01 #v1.0.14
54+
with:
55+
az_client_id: ${{ secrets.AZURE_VAULT_CLIENT_ID }}
56+
az_tenant_id: ${{ secrets.AZURE_VAULT_TENANT_ID }}
57+
az_subscription_id: ${{ secrets.AZURE_VAULT_SUBSCRIPTION_ID }}
58+
keyvault: ${{ secrets.DOCS_VAULTNAME }}
59+
secrets-filter: 'NginxOrgAwsAccountID,NginxOrgAwsRoleName,NginxOrgAllowedUsers'
60+
4861
- name: Check if we're in the allowed environment
62+
env:
63+
ALLOWED_USERS: ${{ env.NginxOrgAllowedUsers }}
64+
DEPLOYMENT_ENV: ${{ inputs.deployment_env }}
4965
run: |
5066
org_found=0
5167
event_found=0
@@ -54,22 +70,22 @@ jobs:
5470
ALLOWED_ORGS="nginx nginxinc"
5571
ALLOWED_EVENTS="push workflow_dispatch"
5672
ALLOWED_REFS="refs/heads/main"
57-
ALLOWED_USERS="${{ secrets.ALLOWED_USERS }}"
73+
USER_LIST="$(printf '%s' "$ALLOWED_USERS" | tr ',\n' ' ')"
5874
for org in $ALLOWED_ORGS; do
5975
if [ "$org" == "$GITHUB_REPOSITORY_OWNER" ]; then org_found=1; fi
6076
done
6177
for event in $ALLOWED_EVENTS; do
6278
if [ "$event" == "$GITHUB_EVENT_NAME" ]; then event_found=1; fi
6379
done
6480
for ref in $ALLOWED_REFS; do
65-
if [ ${{ inputs.deployment_env }} == 'prod' ]; then
81+
if [ "$DEPLOYMENT_ENV" = "prod" ]; then
6682
if [ "$ref" == "$GITHUB_REF" ]; then ref_found=1; fi
6783
else
6884
ref_found=1
6985
fi
7086
done
71-
for user in $ALLOWED_USERS; do
72-
if [ ${{ inputs.deployment_env }} == 'prod' ]; then
87+
for user in $USER_LIST; do
88+
if [ "$DEPLOYMENT_ENV" = "prod" ]; then
7389
if [ "$user" == "$GITHUB_ACTOR" ]; then user_found=1; fi
7490
else
7591
user_found=1
@@ -80,14 +96,7 @@ jobs:
8096
exit 1
8197
fi
8298
exit 0
83-
84-
build-staging:
85-
name: build-staging
86-
runs-on: ubuntu-latest
87-
needs: check-if-allowed
88-
if: ${{ inputs.deployment_env == 'staging' }}
8999
90-
steps:
91100
- name: Install dependencies
92101
run: |
93102
sudo apt-get update
@@ -96,10 +105,10 @@ jobs:
96105
- name: Checkout
97106
uses: actions/checkout@v4
98107

99-
- name: Configure AWS credentials
108+
- name: Configure AWS credentials via OIDC (assume role)
100109
uses: aws-actions/configure-aws-credentials@v4
101110
with:
102-
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }}
111+
role-to-assume: arn:aws:iam::${{ env.NginxOrgAwsAccountID }}:role/${{ env.NginxOrgAwsRoleName }}
103112
aws-region: ${{ inputs.aws_region }}
104113

105114
- name: Build
@@ -149,13 +158,15 @@ jobs:
149158
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/staging/.deployed.txt
150159
151160
- name: Deployment summary
161+
env:
162+
DEPLOYMENT_ENV: ${{ inputs.deployment_env }}
152163
run: |
153164
{
154165
echo "### Deployment Summary"
155166
echo ""
156167
echo "| Key | Value |"
157168
echo "|------------------|-------|"
158-
echo "| deployment_env | ${{ inputs.deployment_env }} |"
169+
echo "| deployment_env | $DEPLOYMENT_ENV |"
159170
echo "| repository | $GITHUB_REPOSITORY |"
160171
echo "| actor | $GITHUB_ACTOR |"
161172
echo "| commit | $GITHUB_SHA |"
@@ -165,14 +176,63 @@ jobs:
165176
build-prod:
166177
name: build-prod
167178
runs-on: ubuntu-latest
168-
needs: check-if-allowed
179+
environment: preview
169180
if: ${{ inputs.deployment_env == 'prod' }}
170181

182+
171183
steps:
172-
- name: Configure AWS credentials
184+
- name: Get Secrets from Azure Key Vault
185+
uses: nginxinc/docs-actions/.github/actions/az-sync@129ceed709adf17d9bfad75bd31a6ec0dbf1cd01 #v1.0.14
186+
with:
187+
az_client_id: ${{ secrets.AZURE_VAULT_CLIENT_ID }}
188+
az_tenant_id: ${{ secrets.AZURE_VAULT_TENANT_ID }}
189+
az_subscription_id: ${{ secrets.AZURE_VAULT_SUBSCRIPTION_ID }}
190+
keyvault: ${{ secrets.DOCS_VAULTNAME }}
191+
secrets-filter: 'NginxOrgAwsAccountID,NginxOrgAwsRoleName,NginxOrgAllowedUsers'
192+
193+
- name: Check if we're in the allowed environment
194+
env:
195+
ALLOWED_USERS: ${{ env.NginxOrgAllowedUsers }}
196+
DEPLOYMENT_ENV: ${{ inputs.deployment_env }}
197+
run: |
198+
org_found=0
199+
event_found=0
200+
ref_found=0
201+
user_found=0
202+
ALLOWED_ORGS="nginx nginxinc"
203+
ALLOWED_EVENTS="push workflow_dispatch"
204+
ALLOWED_REFS="refs/heads/main"
205+
USER_LIST="$(printf '%s' "$ALLOWED_USERS" | tr ',\n' ' ')"
206+
for org in $ALLOWED_ORGS; do
207+
if [ "$org" == "$GITHUB_REPOSITORY_OWNER" ]; then org_found=1; fi
208+
done
209+
for event in $ALLOWED_EVENTS; do
210+
if [ "$event" == "$GITHUB_EVENT_NAME" ]; then event_found=1; fi
211+
done
212+
for ref in $ALLOWED_REFS; do
213+
if [ "$DEPLOYMENT_ENV" = "prod" ]; then
214+
if [ "$ref" == "$GITHUB_REF" ]; then ref_found=1; fi
215+
else
216+
ref_found=1
217+
fi
218+
done
219+
for user in $USER_LIST; do
220+
if [ "$DEPLOYMENT_ENV" = "prod" ]; then
221+
if [ "$user" == "$GITHUB_ACTOR" ]; then user_found=1; fi
222+
else
223+
user_found=1
224+
fi
225+
done
226+
if [ $org_found$event_found$ref_found$user_found -ne 1111 ]; then
227+
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"
228+
exit 1
229+
fi
230+
exit 0
231+
232+
- name: Configure AWS credentials via OIDC (assume role)
173233
uses: aws-actions/configure-aws-credentials@v4
174234
with:
175-
role-to-assume: arn:aws:iam::${{ secrets.AWS_ACCOUNT_ID }}:role/${{ secrets.AWS_ROLE_NAME }}
235+
role-to-assume: arn:aws:iam::${{ env.NginxOrgAwsAccountID }}:role/${{ env.NginxOrgAwsRoleName }}
176236
aws-region: ${{ inputs.aws_region }}
177237

178238
- name: Compute safe repo name
@@ -214,13 +274,15 @@ jobs:
214274
s3://${{ inputs.s3_bucket }}/${{ steps.vars.outputs.safe_repo }}/prod/.deployed.txt
215275
216276
- name: Deployment summary
277+
env:
278+
DEPLOYMENT_ENV: ${{ inputs.deployment_env }}
217279
run: |
218280
{
219281
echo "### Deployment Summary"
220282
echo ""
221283
echo "| Key | Value |"
222284
echo "|------------------|-------|"
223-
echo "| deployment_env | ${{ inputs.deployment_env }} |"
285+
echo "| deployment_env | $DEPLOYMENT_ENV |"
224286
echo "| repository | $GITHUB_REPOSITORY |"
225287
echo "| actor | $GITHUB_ACTOR |"
226288
echo "| commit | $GITHUB_SHA |"

README.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
1. [docs-actions](#docs-actions)
33
1. [Hugo theme version](#hugo-theme-version)
44
1. [az-sync-action](#az-sync-action)
5+
1. [nginx.org-make-aws workflow](nginxorg-make-aws-workflow)
56

67

78
# docs-actions
@@ -194,4 +195,90 @@ A reusable composite action written by s.breen that logs into Azure, retrieves s
194195
Each matched secret is exported as an environment variable named after the secret (e.g. `MySecret1`). Multiline secret values are handled using the heredoc syntax supported by `$GITHUB_ENV`.
195196

196197
---
198+
# nginx.org-make-aws workflow
197199

200+
**Path:** `.github/workflows/nginx.org-make-aws.yml`
201+
202+
A reusable (`workflow_call`) workflow that builds the nginx.org website using `make` and deploys it to AWS S3. It supports two separate jobs controlled by the `deployment_env` input:
203+
204+
- **`build-staging`** — Builds the site from source and syncs the output to a versioned staging path in S3 (`staging/<sha>/`). Also uploads a `.deployed.txt` marker file used by the production job.
205+
- **`build-prod`** — Waits for the staging marker to be present for the current commit SHA, then promotes the staged build to the production S3 path (`prod/`).
206+
207+
Both jobs use the [az-sync](#az-sync-action) action to retrieve AWS credentials from Azure Key Vault before assuming an AWS IAM role via OIDC.
208+
209+
## How-to
210+
These instructions apply only to NGINX GitHub doc repositories.
211+
1. Navigate to the actions section
212+
1. On the left side of the page, select Deploy nginx.org
213+
1. Click a "Run workflow" button.
214+
1. Select select propper "Deployment environment" and press "Run workflow"
215+
The non-prod builds print an URL for the preview which is available in 3-5 minutes.
216+
![Summary](/images/nginx.org.png "nginx.org deploy")
217+
218+
## Secrets
219+
220+
| Secret | Description | Required |
221+
|---|---|---|
222+
| `AZURE_VAULT_CLIENT_ID` | Azure Client ID for Key Vault access | Yes |
223+
| `AZURE_VAULT_SUBSCRIPTION_ID` | Azure Subscription ID | Yes |
224+
| `AZURE_VAULT_TENANT_ID` | Azure Tenant ID | Yes |
225+
| `DOCS_VAULTNAME` | Name of the Azure Key Vault containing AWS credentials | Yes |
226+
227+
The Key Vault referenced by `DOCS_VAULTNAME` must contain the following secrets:
228+
229+
| Key Vault secret | Description |
230+
|---|---|
231+
| `NginxOrgAwsAccountID` | AWS account ID used to construct the IAM role ARN |
232+
| `NginxOrgAwsRoleName` | AWS IAM role name to assume via OIDC |
233+
| `NginxOrgAllowedUsers` | Comma-separated list of GitHub usernames allowed to trigger production deployments |
234+
235+
## Inputs
236+
237+
| Input | Description | Required | Default |
238+
|---|---|---|---|
239+
| `deployment_env` | Target environment: `staging` or `prod` | No | `staging` |
240+
| `url_prod` | Public hostname for the production site | No | `nginx.org` |
241+
| `url_staging` | Public hostname for the staging site | No | `staging.nginx.org` |
242+
| `s3_bucket` | S3 bucket name for deployments | No | `nginx-org-staging` |
243+
| `aws_region` | AWS region for S3 operations | No | `eu-central-1` |
244+
245+
## Access controls
246+
247+
Both jobs verify that the workflow is triggered from an allowed context before proceeding:
248+
249+
- **Organization**: `nginx` or `nginxinc`
250+
- **Event**: `push` or `workflow_dispatch`
251+
- **Ref** (prod only): `refs/heads/main`
252+
- **Actor** (prod only): must be listed in the `NginxOrgAllowedUsers` Key Vault secret
253+
254+
## Caller example
255+
256+
```yml
257+
name: nginx.org build and deploy
258+
259+
on:
260+
push:
261+
branches:
262+
- main
263+
workflow_dispatch:
264+
inputs:
265+
deployment_env:
266+
description: 'Target environment'
267+
required: false
268+
default: staging
269+
type: choice
270+
options:
271+
- staging
272+
- prod
273+
274+
jobs:
275+
call-nginx-org-build:
276+
uses: nginxinc/docs-actions/.github/workflows/nginx.org-make-aws.yml@main
277+
with:
278+
deployment_env: ${{ inputs.deployment_env || 'staging' }}
279+
secrets:
280+
AZURE_VAULT_CLIENT_ID: ${{ secrets.AZURE_VAULT_CLIENT_ID }}
281+
AZURE_VAULT_SUBSCRIPTION_ID: ${{ secrets.AZURE_VAULT_SUBSCRIPTION_ID }}
282+
AZURE_VAULT_TENANT_ID: ${{ secrets.AZURE_VAULT_TENANT_ID }}
283+
DOCS_VAULTNAME: ${{ secrets.DOCS_VAULTNAME }}
284+
```

images/nginx.org.png

232 KB
Loading

0 commit comments

Comments
 (0)