Skip to content

Commit

Permalink
Merge pull request #5 from cagov/dynamic-backend-preview
Browse files Browse the repository at this point in the history
Dynamic back-end preview
  • Loading branch information
xjensen authored Nov 9, 2023
2 parents 248b1f1 + d18370b commit c09e0e0
Show file tree
Hide file tree
Showing 10 changed files with 149 additions and 89 deletions.
40 changes: 4 additions & 36 deletions .github/workflows/deploy_pr.yml
Original file line number Diff line number Diff line change
@@ -1,25 +1,15 @@
name: PR preview deployment
name: PR preview notification
on:
pull_request:
types:
- opened
- synchronize
- ready_for_review
- reopened

jobs:
build_deploy:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v3

- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18

- name: Get branch name (merge)
if: github.event_name != 'pull_request'
shell: bash
Expand All @@ -38,32 +28,10 @@ jobs:
shell: bash
run: echo ${URLSAFE_BRANCH_NAME}

- name: Build
run: |
npm install
npm run widget:build
npm run widget:build:preview -- ${URLSAFE_BRANCH_NAME} ${PRNum}
env:
PRNum: ${{ github.event.number }}

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-west-1

- name: Deploy to S3
run: aws s3 sync ./widget/dist s3://staging.cdn.innovation.ca.gov/br/pr/${URLSAFE_BRANCH_NAME} --follow-symlinks

- name: Invalidate Cloudfront
env:
AWS_RETRY_MODE: standard
AWS_MAX_ATTEMPTS: 6
run: aws cloudfront create-invalidation --distribution-id EPGKQG9OR4C9S --paths "/br/*"

- name: Post URL to PR
uses: mshick/add-pr-comment@v2
with:
message: |
[Widget preview available](https://staging.cdn.innovation.ca.gov/br/pr/${{ env.URLSAFE_BRANCH_NAME }}/preview/index.html).
[Widget preview page.](https://staging.cdn.innovation.ca.gov/br/pr/${{ env.URLSAFE_BRANCH_NAME }}/preview/index.html)
(You may need to wait a minute or two for the latest preview to appear at the above link.)
38 changes: 0 additions & 38 deletions .github/workflows/deploy_prod.yml

This file was deleted.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"api:test": "node tests/http-test.js",
"widget:build": "npm run build --workspace=widget",
"widget:build:preview": "npm run build:preview --workspace=widget",
"serve": "node serve/stack-server.js"
"serve": "node utils/stack-server.js",
"deploy": "npx arc deploy --name test"
},
"devDependencies": {
"@architect/architect": "^10.14.2",
Expand Down
60 changes: 60 additions & 0 deletions utils/deploy-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#!/bin/sh

# Useful variables for development...
# CODEBUILD_WEBHOOK_HEAD_REF="refs/heads/the-branch"
# CODEBUILD_WEBHOOK_TRIGGER="pr/5"
# BENEFITS_RECS_DEPLOY_OUTPUT="✓ Success! Deployed app in 55.815 seconds\n https://7ksmy2xna5.execute-api.us-west-1.amazonaws.com\n"

# Get the name for our arc.codes instance.
if [ -z "$CODEBUILD_WEBHOOK_HEAD_REF" ]
then
# Provide this default if we're testing and the PR info isn't available.
BENEFITS_RECS_INSTANCE_NAME="codebuild-test"
else
# Strip "refs/heads/" from the GitHub ref.
BENEFITS_RECS_INSTANCE_NAME=$(echo ${CODEBUILD_WEBHOOK_HEAD_REF#refs\/heads\/} | sed 's|[^A-Za-z0-9-]|-|g' | sed -E 's|-*([A-Za-z0-9]*.*[A-Za-z0-9]+)-*|\1|')
fi

# Get the PR number.
if [ -z "$CODEBUILD_WEBHOOK_TRIGGER" ]
then
BENEFITS_RECS_PR_NUMBER="9999"
else
# strip "pr/" from webhook trigger
BENEFITS_RECS_PR_NUMBER=${CODEBUILD_WEBHOOK_TRIGGER#pr\/}
fi

echo "\n> Deploying arc.codes app."
echo "PR number: $BENEFITS_RECS_PR_NUMBER"
echo "Git branch: $BENEFITS_RECS_INSTANCE_NAME"

# Attempt to deploy. This will appear to hang. Just wait for it.
BENEFITS_RECS_DEPLOY_OUTPUT=$(npx arc deploy --name $BENEFITS_RECS_INSTANCE_NAME --tags odieng=benefts-recommender --tags env=development --tags branch=$BENEFITS_RECS_INSTANCE_NAME)
BENEFITS_RECS_DEPLOY_STATUS=$?

# If deployment failed, let's bail out here.
if [ $BENEFITS_RECS_DEPLOY_STATUS -gt 0 ]
then
echo "$BENEFITS_RECS_DEPLOY_OUTPUT"
exit $BENEFITS_RECS_DEPLOY_STATUS
fi

BENEFITS_RECS_ENDPOINT_URL=$(echo "$BENEFITS_RECS_DEPLOY_OUTPUT" | tail -n 2 | xargs | sed 's/\\x1B\[\?25h//g')
echo " <= That's ANSI escape output from capturing the deploy logs."

echo "Endpoint: $BENEFITS_RECS_ENDPOINT_URL"

echo "\n> Generating front-end preview assets."
npm run widget:build
npm run widget:build:preview -- $BENEFITS_RECS_INSTANCE_NAME $BENEFITS_RECS_PR_NUMBER $BENEFITS_RECS_ENDPOINT_URL

echo "\n> Uploading to S3."
aws s3 sync ./widget/dist s3://staging.cdn.innovation.ca.gov/br/pr/$BENEFITS_RECS_INSTANCE_NAME --follow-symlinks

echo "\n> Sending invalidation to Cloudfront cache."
AWS_PAGER=""
AWS_RETRY_MODE="standard"
AWS_MAX_ATTEMPTS=6
aws cloudfront create-invalidation --distribution-id EPGKQG9OR4C9S --paths "/br/*"

echo "\nPreview: https://staging.cdn.innovation.ca.gov/br/pr/$BENEFITS_RECS_INSTANCE_NAME/preview/index.html"
20 changes: 20 additions & 0 deletions utils/deploy-prod.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh

echo "\n> Deploying arc.codes app to production."
# Attempt to deploy. This will appear to hang. Just wait for it.
npx arc deploy --production --tags odieng=benefts-recommender --tags env=production

echo "\n> Generating front-end preview assets."
npm run widget:build
npm run widget:build:preview

echo "\n> Uploading to S3."
aws s3 sync ./widget/dist s3://cdn.innovation.ca.gov/br/ --follow-symlinks

echo "\n> Sending invalidation to Cloudfront cache."
AWS_RETRY_MODE="standard"
AWS_MAX_ATTEMPTS=6
AWS_PAGER=""
aws cloudfront create-invalidation --distribution-id EAQBFZOLKQ2AZ --paths "/br/*"

echo "\nApp deployed to production."
30 changes: 30 additions & 0 deletions utils/destroy-pr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/bin/sh

# Useful variables for development...
# CODEBUILD_WEBHOOK_HEAD_REF="refs/heads/the-branch"

# Get the name for our arc.codes instance.
if [ -z "$CODEBUILD_WEBHOOK_HEAD_REF" ]
then
# Provide this default if we're testing and the PR info isn't available.
BENEFITS_RECS_INSTANCE_NAME="codebuild-test"
else
# Strip "refs/heads/" from the GitHub ref.
BENEFITS_RECS_INSTANCE_NAME=$(echo ${CODEBUILD_WEBHOOK_HEAD_REF#refs\/heads\/} | sed 's|[^A-Za-z0-9-]|-|g' | sed -E 's|-*([A-Za-z0-9]*.*[A-Za-z0-9]+)-*|\1|')
fi

echo "\n> Deleting arc.codes app."
echo "Git branch: $BENEFITS_RECS_INSTANCE_NAME"

# Attempt to delete. This will appear to hang. Just wait for it.
npx arc destroy --app benefits-recommendation-api --name $BENEFITS_RECS_INSTANCE_NAME --force

if [ -n "$BENEFITS_RECS_INSTANCE_NAME" ]
then
echo "\n> Removing from S3."
aws s3 rm s3://staging.cdn.innovation.ca.gov/br/pr/$BENEFITS_RECS_INSTANCE_NAME/ --recursive
else
echo "Skipping S3 delete due to blank git branch name."
fi

echo "App deleted."
File renamed without changes.
19 changes: 17 additions & 2 deletions widget/preview/env-picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,23 @@ const getHostOptions = async () => {
});
};

const hydrateMenus = async () => {
const hydrateMenus = async (endpoint = undefined, branch = undefined) => {
const menus = { ...defaultMenus };
const widget = document.querySelector("cagov-benefits-recs");

const hosts = (await getHostOptions()) || [];
menus.host.options = [...menus.host.options, ...hosts];

if (endpoint && branch) {
const extraEndpoint = {
id: branch,
value: endpoint,
text: branch,
};

menus.endpoint.options.push(extraEndpoint);
}

Object.keys(menus).forEach((key) => {
const selObj = menus[key];
const currentValue = widget.hasAttribute(selObj.attribute)
Expand All @@ -170,7 +180,12 @@ class EnvPicker extends window.HTMLElement {
}

async connectedCallback() {
const menus = await hydrateMenus();
// this.endpoint and this.branch are not the currently active values for the widget.
// They're just extra, static values we can use to create an additional endpoint option.
this.endpoint = this.getAttribute("endpoint");
this.branch = this.getAttribute("branch");

const menus = await hydrateMenus(this.endpoint, this.branch);
this.menus = menus;
const initialHtml = generateHtml(this.menus);

Expand Down
27 changes: 16 additions & 11 deletions widget/preview/generate.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
const fs = require("fs/promises");

const generate = (props) => {
const pr = props.prNumber
? `(<a href="https://github.com/cagov/benefits-recommender/pull/${props.prNumber}">Pull Request #${props.prNumber}</a>)`
const { prNumber, endpointUrl, branchName } = props;

const prLink = prNumber
? `(<a href="https://github.com/cagov/benefits-recommender/pull/${prNumber}">Pull Request #${props.prNumber}</a>)`
: "";

const endpointAttribute = endpointUrl ? `endpoint="${endpointUrl}"` : "";
const branchNameAttribute = branchName ? `branch="${branchName}"` : "";

return /* html */ `
<!doctype html>
<html lang="en-US">
Expand All @@ -18,18 +23,16 @@ const generate = (props) => {
<body>
<main>
<hgroup>
<h1>Benefits Recommender Preview</h1>
<p>Widget branch: ${props.widgetEnv} ${pr}</p>
<env-picker></env-picker>
<h1>Benefits Recommender Preview!</h1>
<p>Widget branch: ${branchName} ${prLink}</p>
<env-picker ${endpointAttribute} ${branchNameAttribute}></env-picker>
</hgroup>
<p>Here's some test content.</p>
<p>The widget follows.</p>
<div id="widget-box">
<cagov-benefits-recs
endpoint="https://staging.br.api.innovation.ca.gov">
</cagov-benefits-recs>
<cagov-benefits-recs ${endpointAttribute}></cagov-benefits-recs>
</div>
<p>Site content runs below the widget too.</p>
Expand All @@ -43,16 +46,18 @@ const generate = (props) => {

(async () => {
// CLI:
// node generate.js WIDGET-BRANCH PR-NUMBER
// node generate.js GIT-BRANCH PR-NUMBER
// node generate.js my-upcoming-change-branch 12
const args = process.argv;

const widgetEnv = args[2] || "main";
const branchName = args[2] || "main";
const prNumber = args[3] || undefined;
const endpointUrl = args[4] || undefined;

const html = generate({
widgetEnv,
branchName,
prNumber,
endpointUrl,
});

await fs.mkdir("dist/preview", { recursive: true });
Expand Down
1 change: 0 additions & 1 deletion widget/preview/local.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ <h1>Benefits Recommender Preview</h1>

<div id="widget-box">
<cagov-benefits-recs
host="https://sdio.edd.ca.gov/DIAE/Pages/ExternalUser/InitialClaim/Confirmation.aspx"
endpoint="http://localhost:3333"
></cagov-benefits-recs>
</div>
Expand Down

0 comments on commit c09e0e0

Please sign in to comment.