Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Percy GHA Migration - PR Status check reflects Percy diff state #5092

Closed
57 changes: 0 additions & 57 deletions .circleci/config.yml

This file was deleted.

39 changes: 39 additions & 0 deletions .github/workflows/pr-percy-prepare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: "Prepare Percy build"

on:
pull_request:
branches:
- main

jobs:
copy_artifact:
name: Copy changed files to GHA artifact
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
sparse-checkout: |
templates/docs/examples/
scss/

- name: Make artifact directory
run: |
mkdir -p artifact
cp -R templates/docs/examples/ scss/ artifact/.

# Archive the PR number associated with this workflow since it won't be available in the base workflow context
# https://github.com/orgs/community/discussions/25220
- name: Archive PR data
if: github.event_name=='pull_request'
working-directory: artifact
run: |
echo ${{ github.event.number }} > pr_num.txt
echo ${{ github.event.pull_request.head.sha }} > pr_head_sha.txt

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: "web-artifact-${{ github.run_id }}"
path: |
artifact/*
220 changes: 220 additions & 0 deletions .github/workflows/pr-percy-snapshots.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
name: "Percy screenshots"

on:
workflow_run:
workflows:
- "Prepare Percy build"
types:
- completed

jobs:
upload:
name: Build project with proposed changes & take Percy snapshots
if: github.event.workflow_run.conclusion=='success'
runs-on: ubuntu-latest
outputs:
pr_head_sha: ${{ steps.get_pr_data.outputs.sha }}
pr_number: ${{ steps.get_pr_data.outputs.pr }}
percy_build_link: ${{ steps.percy_snapshot.outputs.build_link }}
percy_org_id: ${{ steps.percy_snapshot.outputs.org_id }}
percy_build_id: ${{ steps.percy_snapshot.outputs.build_id }}
percy_build_state: ${{ steps.percy_build_results.outputs.build_state }}
percy_num_snapshots: ${{ steps.percy_build_results.outputs.num_snapshots }}
percy_review_state: ${{ steps.percy_build_results.outputs.review_state }}
percy_review_state_reason: ${{ steps.percy_build_results.outputs.review_state_reason }}
steps:

- name: Checkout SCM
uses: actions/checkout@v4

- name: Remove SCM files that will be replaced by artifact files
run: rm -rf scss/ templates/docs/examples/

- name: Download artifact from workflow run
uses: actions/download-artifact@v4
with:
name: "web-artifact-${{ github.event.workflow_run.id }}"
github-token: ${{ secrets.GITHUB_TOKEN }}
repository: ${{ github.event.workflow_run.repository.full_name }}
run-id: ${{ github.event.workflow_run.id }}

- name: Get PR data
if: github.event.workflow_run.event=='pull_request'
id: get_pr_data
run: |
set -e
echo "sha=$(cat pr_head_sha.txt)" >> $GITHUB_OUTPUT
echo "pr=$(cat pr_num.txt)" >> $GITHUB_OUTPUT

- name: Move artifact files into place to replace SCM
run: |
set -e
mv examples/ templates/docs/.

- name: Install Python
uses: actions/setup-python@v5.1.0
with:
python-version: 3.10.14

- name: Install NodeJS
uses: actions/setup-node@v4.0.2
with:
node-version: 20

- name: Install dependencies
run: yarn && pip3 install -r requirements.txt

- name: Build
run: yarn build

- name: Start testing server
env:
SECRET_KEY: local_development_fake_key
run: ./entrypoint 0.0.0.0:8101 &

- name: Wait for server availability
run: |
set -e
sleep_interval_secs=2
max_wait_time_secs=30
wait_time_secs=0
while [ "$wait_time_secs" -lt "$max_wait_time_secs" ]; do
if curl -s localhost:8101/_status/check -I; then
echo "Server is up!"
# sometimes if we start the server too soon after it starts responding, percy snapshot errors.
sleep 5
break
else
wait_time_secs=$((wait_time_secs + sleep_interval_secs))
if [ "$wait_time_secs" -ge "$max_wait_time_secs" ]; then
echo "[TIMEOUT ERROR]: Local testing server failed to respond within $max_wait_time_secs seconds!"
exit 1
else
echo "Waiting for server to start..."
sleep "$sleep_interval_secs"
fi
fi
done

- name: Take snapshots & upload to Percy
id: percy_snapshot
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN_WRITE }}
# This identifies the diff in the percy diffs list
PERCY_BRANCH: "pull/${{ steps.get_pr_data.outputs.pr }}"
PERCY_COMMIT: ${{ steps.get_pr_data.outputs.sha }}
PERCY_CLIENT_ERROR_LOGS: false
run: |
set -e

# Start a percy build and capture the stdout
percy_output=$(yarn percy)

# Fail if the Percy stdout contains "Build not created"
if [[ $percy_output =~ "Build not created" ]]; then
echo "Build not created."
exit 1
else
echo "Build created successfully"
echo $percy_output
fi

# Extract the build link from the stdout of the snapshot command
build_link=$(echo "$percy_output" | sed -n 's/.*Finalized build #.*: \(https:\/\/percy.io\/[^ ]*\).*/\1/p')

# Using '/' to split the $build_link, extract the organization and build identifiers
org_id=$(echo "$build_link" | cut -d '/' -f 4)
build_id=$(echo "$build_link" | cut -d '/' -f 7)

echo "build_link=$build_link" >> $GITHUB_OUTPUT
echo "org_id=$org_id" >> $GITHUB_OUTPUT
echo "build_id=$build_id" >> $GITHUB_OUTPUT

echo "Percy build created at $build_link"

- name: Wait for Percy build to complete
run: npx percy build:wait --build ${{ steps.percy_snapshot.outputs.build_id }}
env:
PERCY_TOKEN: ${{ secrets.PERCY_TOKEN_READ }}

# See endpoint docn: https://www.browserstack.com/docs/percy/api-reference/builds#get-build-details
- name: Get Percy build results
id: percy_build_results
run: |
# Fetch Percy build details
response=$(curl --request GET \
--url https://percy.io/api/v1/builds/${{ steps.percy_snapshot.outputs.build_id }} \
--header "Authorization: Token ${{ secrets.PERCY_TOKEN_READ }}"
)

# Extract attributes of build and remove quotes
build_state=$(echo $response | jq '.data.attributes."state"' | tr -d '"')
review_state=$(echo $response | jq '.data.attributes."review-state"' | tr -d '"')
review_state_reason=$(echo $response | jq '.data.attributes."review-state-reason"' | tr -d '"')
num_snapshots=$(echo $response | jq '.data.attributes."total-snapshots"' | tr -d '"')

echo "build state $build_state"
echo "review_state $review_state"
echo "review_state_reason $review_state_reason"
echo "num_snapshots $num_snapshots"

echo "build_state=$build_state" >> $GITHUB_OUTPUT
echo "review_state=$review_state" >> $GITHUB_OUTPUT
echo "review_state_reason=$review_state_reason" >> $GITHUB_OUTPUT
echo "num_snapshots=$num_snapshots" >> $GITHUB_OUTPUT

if [ "$review_state" != "approved" ]; then
echo "Percy diffs were detected."
exit 1
fi

- name: Create successful Percy status check
if: github.event.workflow_run.event=='pull_request'
id: create_percy_final_status_check
uses: octokit/request-action@v2.x
with:
route: POST /repos/${{ github.repository }}/check-runs
owner: octokit
repo: request-action
name: "percy_upload"
head_sha: ${{ steps.get_pr_data.outputs.sha }}
status: completed
conclusion: success
details_url: ${{ steps.percy_snapshot.outputs.build_link }}
output: |
title: "Percy build"
summary: "Percy build #${{ steps.percy_snapshot.outputs.build_id }} completed: ${{ steps.percy_build_results.outputs.review_state }}"
text: |
Percy build was finished at ${{ steps.percy_snapshot.outputs.build_link }}
Build is associated with PR https://github.com/${{github.repository}}/pull/${{ steps.get_pr_data.outputs.pr }}
There were ${{ steps.percy_build_results.outputs.num_snapshots }} total snapshot(s) taken.
The review state reason is: ${{ steps.percy_build_results.outputs.review_state_reason }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
failure_cleanup:
name: Cleanup & report failure
runs-on: ubuntu-latest
needs: upload
if: ${{ failure() }}
steps:
- name: Create failure Percy status check
if: ${{ github.event.workflow_run.event=='pull_request' }}
uses: octokit/request-action@v2.x
with:
route: POST /repos/${{ github.repository }}/check-runs
owner: octokit
repo: request-action
name: "percy_upload"
head_sha: ${{ needs.upload.outputs.pr_head_sha }}
status: completed
conclusion: failure
details_url: ${{ needs.upload.outputs.percy_build_link }}
output: |
title: "Percy build"
summary: "Percy build failed: ${{ needs.upload.outputs.percy_review_state || 'Unknown review state' }}"
text: |
Percy build failed or did not start.
Build is associated with PR https://github.com/${{ github.repository }}/pull/${{ needs.upload.outputs.pr_number }}
The review state reason is: ${{ needs.upload.outputs.percy_review_state_reason }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# ![vanilla](https://assets.ubuntu.com/v1/70041419-vanilla-framework.png?w=35 'Vanilla') Vanilla Framework

[![CircleCI build status](https://circleci.com/gh/canonical/vanilla-framework.svg?style=shield)](https://circleci.com/gh/canonical/vanilla-framework)
[![npm version](https://badge.fury.io/js/vanilla-framework.svg)](http://badge.fury.io/js/vanilla-framework)
[![Downloads](http://img.shields.io/npm/dm/vanilla-framework.svg)](https://www.npmjs.com/package/vanilla-framework)
[![devDependency Status](https://david-dm.org/canonical/vanilla-framework/dev-status.svg)](https://david-dm.org/canonical/vanilla-framework#info=devDependencies)
Expand Down
Loading