Skip to content

Commit

Permalink
Add centralized staging build files for docs-staging-x deploys (#53586)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ebonsignori authored Jan 11, 2025
1 parent 3a792f8 commit fc769e1
Show file tree
Hide file tree
Showing 18 changed files with 1,004 additions and 0 deletions.
164 changes: 164 additions & 0 deletions .github/workflows/sync-staging-repo-files.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# **What it does**: Synchronizes each of the github/docs-staging-X repositories with the latest build scripts, workflows, and other files from src/deployments/staging.
# **Why we have it**: We want to centralize build config in src/deployments/staging for use across multiple repos.
# **Who does it impact**: Docs engineering, and potentially content writers.

name: Sync Staging Repo Files

on:
push:
branches: [main]
paths:
- 'src/deployments/staging/build-scripts/*.sh'
- 'src/deployments/staging/.github/**'
- 'src/deployments/staging/Dockerfile'
- 'src/deployments/staging/.env.example'
- 'src/deployments/staging/README.example.md'
- 'src/deployments/staging/config/**'

permissions:
contents: write

jobs:
# Determine how many staging repos we have and generate a matrix with repo and index
generate-matrix:
if: github.repository == 'github/docs-internal'
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout source repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 1 # Only need latest commit for config.json

- name: Read configuration
id: read-config
run: |
sudo apt-get update && sudo apt-get install -y jq
NUMBER_OF_REPOS=$(jq '.number_of_staging_repos' src/deployments/staging/config.json)
if ! [[ "$NUMBER_OF_REPOS" =~ ^[0-9]+$ ]]; then
echo "Invalid number_of_staging_repos in config.json: $NUMBER_OF_REPOS"
exit 1
fi
echo "number_of_repos=$NUMBER_OF_REPOS" >> $GITHUB_OUTPUT
- name: Generate repository list with indices
id: generate-repos
run: |
NUMBER_OF_REPOS=${{ steps.read-config.outputs.number_of_repos }}
repos=()
for i in $(seq 0 $NUMBER_OF_REPOS); do
repos+=("{\"repo\": \"github/docs-staging-$i\", \"index\": $i}")
done
json_repos=$(printf '%s\n' "${repos[@]}" | jq -s .)
echo "repos=$json_repos" >> $GITHUB_OUTPUT
- name: Set matrix output with repo and index
id: set-matrix
run: |
repos=${{ steps.generate-repos.outputs.repos }}
echo "matrix={\"include\": $repos}" >> $GITHUB_OUTPUT
- uses: ./.github/actions/slack-alert
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
with:
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}

sync:
if: github.repository == 'github/docs-internal'
needs: generate-matrix
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix) }}
steps:
- name: Checkout source repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 0

- name: Checkout target repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
repository: ${{ matrix.repo }}
token: ${{ secrets.DOCS_BOT_PAT_READPUBLICKEY }}
path: target_repo
fetch-depth: 0

- name: Synchronize files to target repo
run: |
# Create necessary directories if they DNE
mkdir -p target_repo/build-scripts
mkdir -p target_repo/.github/workflows
mkdir -p target_repo/config
# Copy build scripts
cp src/deployments/staging/build-scripts/*.sh target_repo/build-scripts/ || true
# Copy .github directory
cp -r src/deployments/staging/.github target_repo/
# Copy config files
cp -r src/deployments/staging/config/* target_repo/config/ || true
# Overwrite Dockerfile
cp src/deployments/staging/Dockerfile target_repo/Dockerfile
# Conditional copy for .env if not present
if [ ! -f target_repo/.env ]; then
cp src/deployments/staging/.env.example target_repo/.env
fi
# Conditional copy for README.md if not present
if [ ! -f target_repo/README.md ]; then
cp src/deployments/staging/README.example.md target_repo/README.md
fi
- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq

- name: Replace template variables
run: |
# Determine which values to use based on the index
INDEX=${{ matrix.index }}
if [ "$INDEX" -eq 0 ]; then
DOMAIN=$(jq -r '.server_domain_name.internal' src/deployments/staging/config.json)
LOADBALANCER=$(jq -r '.load_balancer_type.internal' src/deployments/staging/config.json)
elif [ "$INDEX" -eq 1 ]; then
DOMAIN=$(jq -r '.server_domain_name.external' src/deployments/staging/config.json)
LOADBALANCER=$(jq -r '.load_balancer_type.external' src/deployments/staging/config.json)
else
DOMAIN=$(jq -r '.server_domain_name["docs-staging-x"]' src/deployments/staging/config.json)
LOADBALANCER=$(jq -r '.load_balancer_type.["docs-staging-x"]' src/deployments/staging/config.json)
# Replace {{x}} in the domain variable with the current index
DOMAIN=$(echo "$DOMAIN" | sed "s/{{x}}/$INDEX/g")
fi
# Perform replacements in target_repo files
# Replace the server_domain_name and load_balancer_type
find target_repo -type f -exec sed -i "s|{{server_domain_name}}|$DOMAIN|g" {} +
find target_repo -type f -exec sed -i "s|{{load_balancer_type}}|$LOADBALANCER|g" {} +
# If any files still contain {{x}}, replace them with the current index
find target_repo -type f -exec sed -i "s/{{x}}/$INDEX/g" {} +
- name: Commit and push changes
run: |
cd target_repo
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
# If there are changes, commit and push
if ! git diff --cached --quiet; then
git commit -m "Synchronize files from source repository with index ${{ matrix.index }}"
git push
fi
- uses: ./.github/actions/slack-alert
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
with:
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
119 changes: 119 additions & 0 deletions .github/workflows/update-docs-staging-x-repo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# **What it does**: Triggers a repo disaptch event when pushing to a `docs-staging-x` branch
# or when a PR is labeled with `docs-staging-x`. The repo dispatch updates the corresponding
# docs-staging-x repo with the latest commit SHA, which triggers a deployment.
#
# Note: This does not work for docs-staging-{0/1} (review servers) updates to those are
# handled in the `update-review-servers-on-code-push.yml` workflow.
#
# **Why we have it**: Makes staging deployments easy
# **Who does it impact**: Anyone trying to deploy a staging branch, both Docs Content and Docs Engineering

name: Update docs-staging-x

on:
push:
branches:
- 'docs-staging-[0-9]*'
pull_request:
types: [labeled]

permissions:
contents: read

jobs:
dispatch-sha:
if: github.repository == 'github/docs-internal'
runs-on: ubuntu-latest

steps:
# Needed because we call a composite action (Slack alert)
- name: Checkout source repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 1 # Only need latest commit

- name: Determine target staging repo
id: determine_repo
run: |
# Determine the event type
EVENT_TYPE="${{ github.event_name }}"
SHOULD_DISPATCH="false"
if [ "$EVENT_TYPE" = "push" ]; then
# Triggered by a push event
BRANCH_NAME=${GITHUB_REF#refs/heads/}
echo "Triggered by push event on branch: $BRANCH_NAME"
# Extract the staging number from branch name
if [[ "$BRANCH_NAME" =~ ^docs-staging-([0-9]+)$ ]]; then
STAGING_NUMBER="${BASH_REMATCH[1]}"
else
echo "Branch name does not match the required pattern docs-staging-X."
exit 1
fi
# Get the commit SHA from the push event
COMMIT_SHA="${GITHUB_SHA}"
elif [ "$EVENT_TYPE" = "pull_request" ]; then
# Triggered by a PR labeled event
LABEL_NAME="${{ github.event.label.name }}"
echo "Triggered by PR labeled event with label: $LABEL_NAME"
if [[ "$LABEL_NAME" =~ ^docs-staging-([0-9]+)$ ]]; then
STAGING_NUMBER="${BASH_REMATCH[1]}"
else
echo "Label does not match the required pattern docs-staging-X."
# Do not dispatch if it doesn't match
echo "should_dispatch=false" >> $GITHUB_OUTPUT
exit 0
fi
# Get the commit SHA from the pull request head
COMMIT_SHA="${{ github.event.pull_request.head.sha }}"
else
echo "Event type $EVENT_TYPE not supported."
echo "should_dispatch=false" >> $GITHUB_OUTPUT
exit 0
fi
echo "Staging Number: $STAGING_NUMBER"
# Check if staging number is 0 or 1
if [ "$STAGING_NUMBER" = "0" ] || [ "$STAGING_NUMBER" = "1" ]; then
echo "Staging number $STAGING_NUMBER is reserved."
echo "Review server repos are handled in the \`update-review-servers-on-code-push.yml\` repository."
echo "should_dispatch=false" >> $GITHUB_OUTPUT
exit 0
fi
TARGET_REPO="docs-staging-$STAGING_NUMBER"
echo "Target Repository: $TARGET_REPO"
SHOULD_DISPATCH="true"
# Set outputs
echo "target_repo=$TARGET_REPO" >> $GITHUB_OUTPUT
echo "commit_sha=$COMMIT_SHA" >> $GITHUB_OUTPUT
echo "should_dispatch=$SHOULD_DISPATCH" >> $GITHUB_OUTPUT
- name: Dispatch repository dispatch event to staging repo
if: steps.determine_repo.outputs.should_dispatch == 'true'
env:
REPO_DISPATCH_TOKEN: ${{ secrets.DOCS_BOT_PAT_WORKFLOW }}
TARGET_OWNER: github
TARGET_REPO: ${{ steps.determine_repo.outputs.target_repo }}
EVENT_TYPE: update-sha
SHA: ${{ steps.determine_repo.outputs.commit_sha }}
run: |
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $REPO_DISPATCH_TOKEN" \
https://api.github.com/repos/$TARGET_OWNER/$TARGET_REPO/dispatches \
-d "{\"event_type\":\"$EVENT_TYPE\",\"client_payload\":{\"SHA\":\"$SHA\"}}"
- uses: ./.github/actions/slack-alert
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
with:
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
67 changes: 67 additions & 0 deletions .github/workflows/update-review-servers-on-code-push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# **What it does**: Triggers a repo dispatch event when pushing a code change to `main`
# dispatches the latest SHA to both review server repos, `docs-staging-0` and `docs-staging-1`
#
# Note: We only dispatch on code changes to prevent unnecessary deployments since content changes
# won't affect the review servers.
#
# **Why we have it**: Keeps the review servers up-to-date with the latest code changes
# **Who does it impact**: Docs Content and Docs Engineering

name: Update review servers on code push

on:
push:
branches:
- main
paths:
- 'src/**'
- 'package.json'
- 'tsconfig.json'
- 'next.config.js'

permissions:
contents: read

jobs:
dispatch-sha:
if: github.repository == 'github/docs-internal'
runs-on: ubuntu-latest
strategy:
matrix:
target_repo: [docs-staging-0, docs-staging-1]

steps:
# Needed because we call a composite action (Slack alert)
- name: Checkout source repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
fetch-depth: 1 # Only need latest commit

- name: Determine commit SHA and dispatch condition
id: determine_repo
run: |
echo "commit_sha=${GITHUB_SHA}" >> $GITHUB_OUTPUT
# Since this workflow only runs when code changes occur (due to path filters),
# we can always set should_dispatch to true.
echo "should_dispatch=true" >> $GITHUB_OUTPUT
- name: Dispatch repository dispatch event to staging repos
if: steps.determine_repo.outputs.should_dispatch == 'true'
env:
REPO_DISPATCH_TOKEN: ${{ secrets.DOCS_BOT_PAT_WORKFLOW }}
TARGET_OWNER: github
TARGET_REPO: ${{ matrix.target_repo }}
EVENT_TYPE: update-sha
SHA: ${{ steps.determine_repo.outputs.commit_sha }}
run: |
curl -X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token $REPO_DISPATCH_TOKEN" \
https://api.github.com/repos/$TARGET_OWNER/$TARGET_REPO/dispatches \
-d "{\"event_type\":\"$EVENT_TYPE\",\"client_payload\":{\"SHA\":\"$SHA\"}}"
- uses: ./.github/actions/slack-alert
if: ${{ failure() && github.event_name != 'workflow_dispatch' }}
with:
slack_channel_id: ${{ secrets.DOCS_ALERTS_SLACK_CHANNEL_ID }}
slack_token: ${{ secrets.SLACK_DOCS_BOT_TOKEN }}
27 changes: 27 additions & 0 deletions src/deployments/staging/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# The .env file in every docs-staging-X repo can be adjusted freely and is not synchronized

# - - -
# Unique per staging server
# - - -
# The name of the staging branch (should be the same as the repo name except for the review server)
STAGING_BRANCH=docs-staging-{{x}}
# Required for identifing image in datadog metrics
MODA_APP_NAME=docs-staging-{{x}}
# The most recent SHA of the STAGING_BRANCH
SHA={{sha}}

# - - -
# Unique per review server
# - - -
# Empty for regular staging servers, 'internal' or 'external' for review server
REVIEW_SERVER=

# - - -
# Shared defaults
# - - -
NODE_ENV=production
PORT=4000
ENABLED_LANGUAGES='en,zh,es,pt,ru,ja,fr,de,ko'
RATE_LIMIT_MAX='21'
# Moda uses a non-default port for sending datadog metrics
DD_DOGSTATSD_PORT='28125'
Loading

0 comments on commit fc769e1

Please sign in to comment.