зеркало из https://github.com/github/docs.git
Workflow for staging PR deployments on azure (#24039)
* add workflow for staging PR deployments on azure * add workflow to clean up azure staging resources
This commit is contained in:
Родитель
a5af5e4665
Коммит
6c8911eea0
|
@ -0,0 +1,118 @@
|
|||
name: Staging - Azure Deploy App Service
|
||||
|
||||
# **What it does**: Build and deploy staging PRs to Azure
|
||||
# **Why we have it**: It's our new staging deployment mechanism, only applicable to docs-internal
|
||||
# **Who does it impact**: All contributors.
|
||||
|
||||
# This whole workflow is only guaranteed to be secure in the *private
|
||||
# repo* and because we repo-sync these files over the to the public one,
|
||||
# IT'S IMPORTANT THAT THIS WORKFLOW IS ONLY ENABLED IN docs-internal!
|
||||
|
||||
on:
|
||||
# The advantage of 'pull_request' over 'pull_request_target' is that we
|
||||
# can make changes to this file and test them in a pull request, instead
|
||||
# of relying on landing it in 'main' first.
|
||||
# From a security point of view, its arguably safer this way because
|
||||
# unlike 'pull_request_target', these only have secrets if the pull
|
||||
# request creator has permission to access secrets.
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
deployments: write
|
||||
|
||||
# This allows one deploy workflow to interrupt another
|
||||
concurrency:
|
||||
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
if: ${{ github.repository == 'github/docs-internal' }}
|
||||
name: Build and deploy image to staging App Service
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
environment:
|
||||
name: staging-pr-${{ github.event.number }}
|
||||
url: ${{ steps.deploy.outputs.defaultHostName }}
|
||||
env:
|
||||
GITHUB_EVENT_NUMBER: ${{ github.event.number }}
|
||||
NONPROD_REGISTRY_USERNAME: ghdocs
|
||||
# Image tag is unique to each workflow run so that it always triggers a new deployment
|
||||
DOCKER_IMAGE: ${{ secrets.NONPROD_REGISTRY_SERVER }}/${{ github.repository }}/pr-${{ github.event.number }}:${{ github.event.pull_request.head.sha }}-${{ github.run_number }}-${{ github.run_attempt }}
|
||||
|
||||
steps:
|
||||
- name: 'Set env vars'
|
||||
id: vars
|
||||
run: |
|
||||
REPO_NAME=${GITHUB_REPOSITORY#*\/}
|
||||
echo "REPO_NAME=${REPO_NAME}" >> $GITHUB_ENV
|
||||
echo "APP_NAME=gh${REPO_NAME}-staging-${GITHUB_EVENT_NUMBER}" >> $GITHUB_ENV
|
||||
|
||||
- name: 'Az CLI login'
|
||||
uses: azure/login@66d2e78565ab7af265d2b627085bc34c73ce6abb
|
||||
with:
|
||||
creds: ${{ secrets.NONPROD_AZURE_CREDENTIALS }}
|
||||
|
||||
- name: 'Docker login'
|
||||
uses: azure/docker-login@81744f9799e7eaa418697cb168452a2882ae844a
|
||||
with:
|
||||
login-server: ${{ secrets.NONPROD_REGISTRY_SERVER }}
|
||||
username: ${{ env.NONPROD_REGISTRY_USERNAME }}
|
||||
password: ${{ secrets.NONPROD_REGISTRY_PASSWORD }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@94ab11c41e45d028884a99163086648e898eed25
|
||||
|
||||
- name: Check out repo
|
||||
uses: actions/checkout@1e204e9a9253d643386038d443f96446fa156a97
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
# To prevent issues with cloning early access content later
|
||||
persist-credentials: 'false'
|
||||
lfs: 'true'
|
||||
|
||||
- name: Check out LFS objects
|
||||
run: git lfs checkout
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@04c56d2f954f1e4c69436aa54cfef261a018f458
|
||||
with:
|
||||
node-version: 16.13.x
|
||||
cache: npm
|
||||
|
||||
- if: ${{ github.repository == 'github/docs-internal' }}
|
||||
name: Clone early access
|
||||
env:
|
||||
DOCUBOT_REPO_PAT: ${{ secrets.DOCUBOT_REPO_PAT }}
|
||||
GIT_BRANCH: ${{ github.event.pull_request.head.sha }}
|
||||
run: npm install dotenv && node script/early-access/clone-for-build.js
|
||||
|
||||
- name: 'Build and push image'
|
||||
uses: docker/build-push-action@a66e35b9cbcf4ad0ea91ffcaf7bbad63ad9e0229
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
target: ${{ fromJSON('["production", "production_early_access"]')[github.repository == 'github/docs-internal'] }}
|
||||
tags: ${{ env.DOCKER_IMAGE }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# Deploy ARM template is idempotent
|
||||
# Note: once the resources exist the image tag must change for a new deployment to occur (the image tag includes workflow run number, run attempt, as well as sha)
|
||||
- name: Run ARM deploy
|
||||
id: deploy
|
||||
uses: azure/arm-deploy@841b12551939c88af8f6df767c24c38a5620fd0d
|
||||
with:
|
||||
resourceGroupName: docs-nonprod
|
||||
subscriptionId: ${{ secrets.NONPROD_SUBSCRIPTION_ID }}
|
||||
template: ./staging-azure-deploy-template.json
|
||||
parameters: appName="${{ env.APP_NAME }}"
|
||||
location="East US"
|
||||
linuxFxVersion="DOCKER|${{ env.DOCKER_IMAGE }}"
|
||||
dockerRegistryUrl="https://${{ secrets.NONPROD_REGISTRY_SERVER }}"
|
||||
dockerRegistryUsername="${{ env.NONPROD_REGISTRY_USERNAME }}"
|
||||
dockerRegistryPassword="${{ secrets.NONPROD_REGISTRY_PASSWORD }}"
|
||||
|
||||
- run: echo ${{ steps.deploy.outputs.defaultHostName }}
|
|
@ -0,0 +1,50 @@
|
|||
name: Staging - Undeploy Azure PR
|
||||
|
||||
# **What it does**: To undeploy PRs from Azure staging environment, i.e. destroy the App and associated resources.
|
||||
# **Why we have it**: To save money spent on deployments for closed PRs.
|
||||
# **Who does it impact**: All contributors.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
- locked
|
||||
|
||||
jobs:
|
||||
undeploy:
|
||||
name: Undeploy
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
env:
|
||||
GITHUB_EVENT_NUMBER: ${{ github.event.number }}
|
||||
IMAGE_REPO: ${{ github.repository }}/pr-${{ github.event.number }}
|
||||
|
||||
steps:
|
||||
- name: 'Set env vars'
|
||||
id: vars
|
||||
run: |
|
||||
REPO_NAME=${GITHUB_REPOSITORY#*\/}
|
||||
echo "APP_NAME=gh${REPO_NAME}-staging-${GITHUB_EVENT_NUMBER}" >> $GITHUB_ENV
|
||||
|
||||
- name: 'Az CLI login'
|
||||
uses: azure/login@66d2e78565ab7af265d2b627085bc34c73ce6abb
|
||||
with:
|
||||
creds: ${{ secrets.NONPROD_AZURE_CREDENTIALS }}
|
||||
|
||||
# Delete web app (which will also delete the App Service plan)
|
||||
# This will succeed even if the app doesn't exist / has already been deleted
|
||||
- name: 'Delete App Service App (which will also delete the App Service plan)'
|
||||
run: |
|
||||
az webapp delete -n $APP_NAME -g docs-nonprod
|
||||
|
||||
# Untag all images under this PR's container registry repo - the container registry will automatically remove untagged images.
|
||||
# This will fail if the IMAGE_REPO doesn't exist, but we don't care
|
||||
- name: 'Untag all docker images for this PR'
|
||||
run: |
|
||||
az acr repository delete -n ghdocs --repository ${{ env.IMAGE_REPO }} -y || true
|
||||
|
||||
# Remove all deployments from this environment and remove the environment
|
||||
- uses: strumwolf/delete-deployment-environment@45c821e46baa405e25410700fe2e9643929706a0
|
||||
with:
|
||||
token: ${{ secrets.DOCUBOT_REPO_PAT }}
|
||||
environment: staging-pr-${{ github.event.number }}
|
|
@ -30,4 +30,4 @@ jobs:
|
|||
- name: Run linter
|
||||
uses: cschleiden/actions-linter@caffd707beda4fc6083926a3dff48444bc7c24aa
|
||||
with:
|
||||
workflows: '[".github/workflows/*.yml", ".github/workflows/*.yaml", "!.github/workflows/remove-from-fr-board.yaml", "!.github/workflows/staging-deploy-pr.yml", "!.github/workflows/triage-issue-comments.yml"]'
|
||||
workflows: '[".github/workflows/*.yml", ".github/workflows/*.yaml", "!.github/workflows/remove-from-fr-board.yaml", "!.github/workflows/staging-deploy-pr.yml", "!.github/workflows/triage-issue-comments.yml", "!.github/workflows/staging-build-and-deploy-azure.yml"]'
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"appName": {
|
||||
"type": "String"
|
||||
},
|
||||
"location": {
|
||||
"type": "String"
|
||||
},
|
||||
"linuxFxVersion": {
|
||||
"type": "String"
|
||||
},
|
||||
"dockerRegistryUrl": {
|
||||
"type": "String"
|
||||
},
|
||||
"dockerRegistryUsername": {
|
||||
"type": "String"
|
||||
},
|
||||
"dockerRegistryPassword": {
|
||||
"type": "SecureString"
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"appServicePlanName": "[concat('ASP-', parameters('appName'))]"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
|
||||
"type": "Microsoft.Web/serverfarms",
|
||||
"apiVersion": "2021-02-01",
|
||||
"name": "[variables('appServicePlanName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"sku": {
|
||||
"name": "B2"
|
||||
},
|
||||
"kind": "linux",
|
||||
"properties": {
|
||||
"reserved": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Web/sites",
|
||||
"apiVersion": "2018-11-01",
|
||||
"name": "[parameters('appName')]",
|
||||
"location": "[parameters('location')]",
|
||||
"dependsOn": [
|
||||
"[resourceId('Microsoft.Web/serverfarms', variables('appServicePlanName'))]"
|
||||
],
|
||||
"tags": {},
|
||||
"properties": {
|
||||
"name": "[parameters('appName')]",
|
||||
"siteConfig": {
|
||||
"appSettings": [
|
||||
{
|
||||
"name": "DOCKER_REGISTRY_SERVER_URL",
|
||||
"value": "[parameters('dockerRegistryUrl')]"
|
||||
},
|
||||
{
|
||||
"name": "DOCKER_REGISTRY_SERVER_USERNAME",
|
||||
"value": "[parameters('dockerRegistryUsername')]"
|
||||
},
|
||||
{
|
||||
"name": "DOCKER_REGISTRY_SERVER_PASSWORD",
|
||||
"value": "[parameters('dockerRegistryPassword')]"
|
||||
},
|
||||
{
|
||||
"name": "WEBSITES_ENABLE_APP_SERVICE_STORAGE",
|
||||
"value": "false"
|
||||
},
|
||||
{
|
||||
"name": "NODE_ENV",
|
||||
"value": "production"
|
||||
},
|
||||
{
|
||||
"name": "PORT",
|
||||
"value": "4000"
|
||||
},
|
||||
{
|
||||
"name": "DEPLOYMENT_ENV",
|
||||
"value": "azure"
|
||||
},
|
||||
{
|
||||
"name": "WEB_CONCURRENCY",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"name": "ENABLED_LANGUAGES",
|
||||
"value": "en,ja"
|
||||
}
|
||||
],
|
||||
"linuxFxVersion": "[parameters('linuxFxVersion')]",
|
||||
"appCommandLine": "",
|
||||
"alwaysOn": false,
|
||||
"numberOfWorkers": 1,
|
||||
"healthCheckPath": "/healthz",
|
||||
"httpLoggingEnabled": true,
|
||||
"logsDirectorySizeLimit": 35
|
||||
},
|
||||
"serverFarmId": "[concat('/subscriptions/', subscription().id, '/resourcegroups/', resourceGroup().name, '/providers/Microsoft.Web/serverfarms/', variables('appServicePlanName'))]",
|
||||
"clientAffinityEnabled": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
"defaultHostName": {
|
||||
"type": "string",
|
||||
"value": "[concat('https://', parameters('appName'), '.azurewebsites.net')]"
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче