Skip to content

Commit

Permalink
chore(PPDSC-2611): fewer tests for baseline updates (#588)
Browse files Browse the repository at this point in the history
* chore(PPDSC-2611): log which baselines require updating

* chore(PPDSC-2611): only run tests required

* chore(PPDSC-2611): set baselines updates as partial builds

* chore(PPDSC-2611): revert log changes

* chore(PPDSC-2611): simply script and add tests

* chore(PPDSC-2611): simplify token setting
  • Loading branch information
mstuartf authored Jan 30, 2023
1 parent 729b6a4 commit fd4d458
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 37 deletions.
40 changes: 22 additions & 18 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -650,15 +650,17 @@ jobs:
- run:
name: 'Check if updates required'
command: |
{
export PR_BRANCH_NAME=$(gh pr list --search $CIRCLE_SHA1 --state merged --json headRefName --jq '.[].headRefName') &&
echo "Found branch name: ${PR_BRANCH_NAME}" &&
node scripts/check-baseline-updates.js $PR_BRANCH_NAME "comps" &&
echo "No baseline updates required; finishing job." &&
circleci-agent step halt
} || {
echo "Baseline updates required; continuing job."
}
export PR_BRANCH_NAME=$(gh pr list --search $CIRCLE_SHA1 --state merged --json headRefName --jq '.[].headRefName')
echo "Found branch name: ${PR_BRANCH_NAME}"
export PERCY_TOKEN=$PERCY_COMPS_TOKEN
export UPDATES_REQUIRED=$(npx -y run-func scripts/check-baseline-updates.js run $PR_BRANCH_NAME)
if [ $UPDATES_REQUIRED = "true" ]; then
echo "Baseline updates required; continuing job."
export PERCY_PARTIAL_BUILD=1
else
echo "No baseline updates required; finishing job." &&
circleci-agent step halt
fi
- run_test_visual_comps_percy
- slack/notify:
<<: *slack_notify
Expand All @@ -673,15 +675,17 @@ jobs:
- run:
name: 'Check if updates required'
command: |
{
export PR_BRANCH_NAME=$(gh pr list --search $CIRCLE_SHA1 --state merged --json headRefName --jq '.[].headRefName') &&
echo "Found branch name: ${PR_BRANCH_NAME}" &&
node scripts/check-baseline-updates.js $PR_BRANCH_NAME "docsite" &&
echo "No baseline updates required; finishing job." &&
circleci-agent step halt
} || {
echo "Baseline updates required; continuing job."
}
export PR_BRANCH_NAME=$(gh pr list --search $CIRCLE_SHA1 --state merged --json headRefName --jq '.[].headRefName')
echo "Found branch name: ${PR_BRANCH_NAME}"
export PERCY_TOKEN=$PERCY_COMPS_TOKEN
export UPDATES_REQUIRED=$(npx -y run-func scripts/check-baseline-updates.js run $PR_BRANCH_NAME)
if [ $UPDATES_REQUIRED = "true" ]; then
echo "Baseline updates required; continuing job."
export PERCY_PARTIAL_BUILD=1
else
echo "No baseline updates required; finishing job." &&
circleci-agent step halt
fi
- run_test_visual_docs_percy
- slack/notify:
<<: *slack_notify
Expand Down
6 changes: 5 additions & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module.exports = {
projects: ['<rootDir>/src/jest.config.js', '<rootDir>/site/jest.config.js'],
projects: [
'<rootDir>/src/jest.config.js',
'<rootDir>/site/jest.config.js',
'<rootDir>/scripts/jest.config.js',
],
coveragePathIgnorePatterns: ['/node_modules/', '<rootDir>/test'],
coverageReporters: ['lcov', 'text-summary'],
collectCoverage: true,
Expand Down
1 change: 1 addition & 0 deletions percy-storybook.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
2 changes: 2 additions & 0 deletions percy.config.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
const SKIP_GITHUB_CHECK = process.env.SKIP_PERCY_CHECK === 'true';
const storybookConfig = require('./percy-storybook.config.json');

module.exports = {
version: 2,
snapshot: {
widths: [375, 1280],
},
storybook: {
...storybookConfig,
...(SKIP_GITHUB_CHECK ? {include: 'skip-percy-tests'} : {}),
},
};
99 changes: 99 additions & 0 deletions scripts/__tests__/check-baseline-updates.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
const https = require('https');
const fs = require('fs');
const Stream = require('stream');

const {run} = require('../check-baseline-updates');

const BUILDS = {
data: [
{
attributes: {
branch: 'branch/approved-with-diffs',
'review-state': 'approved',
'total-comparisons-diff': '3',
},
relationships: {
snapshots: {
links: {
related: 'branch/approved-with-diffs-related',
},
},
},
},
{
attributes: {
branch: 'branch/approved-no-diffs',
'review-state': 'approved',
'total-comparisons-diff': 0,
},
},
{
attributes: {
branch: 'branch/diffs-not-approved',
'review-state': 'pending',
'total-comparisons-diff': 0,
},
},
],
};

const SNAPSHOTS = {
data: [
{
attributes: {
'review-state-reason': 'user_approved',
name: 'snapshot1',
},
},
{
attributes: {
'review-state-reason': 'user_approved',
name: 'snapshot2',
},
},
],
};

const mockHttp = (url, options, callback) => {
const streamStream = new Stream();
callback(streamStream);
const data = url.includes('/api/v1/builds') ? BUILDS : SNAPSHOTS;
streamStream.emit('data', JSON.stringify(data));
streamStream.emit('end');
};

describe('check-baseline-updates', () => {
beforeEach(() => {
process.env.PERCY_TOKEN = '__PERCY_TOKEN__';
https.get = jest.fn().mockImplementation(mockHttp);
});

it('should update config file and return true if updates required', async () => {
fs.writeFileSync = jest.fn();
const result = await run('branch/approved-with-diffs');
expect(fs.writeFileSync).toHaveBeenCalledWith(
'./percy-storybook.config.json',
JSON.stringify({include: ['^snapshot1$', '^snapshot2$']}),
);
expect(result).toBe(true);
});

it('should return false if no diffs require updates', async () => {
const result = await run('branch/approved-no-diffs');
expect(result).toBe(false);
});

it('should return false if build not approved', async () => {
const result = await run('branch/diffs-not-approved');
expect(result).toBe(false);
});

it('should raise an exception if no token found', async () => {
delete process.env.PERCY_TOKEN;
await expect(run('branch/approved-no-diffs')).rejects.toThrowError();
});

it('should raise an exception if build not found', async () => {
await expect(run('invalid-branch')).rejects.toThrowError();
});
});
50 changes: 32 additions & 18 deletions scripts/check-baseline-updates.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#!/usr/bin/env node
const https = require('https');
const fs = require('fs');

const PERCY_URL = 'https://percy.io/api/v1';
const PERCY_URL = 'https://percy.io';

const CONFIG_FILE = 'percy-storybook.config.json';

const log = value => process.stdout.write(`${value}\n`);

Expand All @@ -21,16 +24,20 @@ function apiCall(url, options) {
});
}

async function getPercyBuildForBranch(branchName, project) {
log(`Looking for Percy ${project} build for branch ${branchName}`);
const token = process.env[`PERCY_${project.toUpperCase()}_TOKEN`];
function percyApiCall(path) {
const token = process.env.PERCY_TOKEN;
if (!token) {
log(`No Percy token found for project ${project}`);
log(`No Percy token found`);
throw Error();
}
const builds = await apiCall(`${PERCY_URL}/builds`, {
return apiCall(`${PERCY_URL}${path}`, {
headers: {Authorization: `Token ${token}`},
});
}

async function getPercyBuildForBranch(branchName) {
log(`Looking for Percy build for branch ${branchName}`);
const builds = await percyApiCall('/api/v1/builds');
for (let i = 0; i <= builds.data.length; i++) {
const build = builds.data[i];
if (build.attributes.branch === branchName) {
Expand All @@ -41,26 +48,33 @@ async function getPercyBuildForBranch(branchName, project) {
throw Error();
}

async function checkIfBaselineUpdatesRequired(headRefName, project) {
async function run(headRefName) {
const branchName = headRefName.trim();
log(
`Checking if baselines for ${project} need to be updated after ${branchName} was merged`,
);
log(`Checking if baselines to be updated after ${branchName} was merged`);

const build = await getPercyBuildForBranch(branchName, project);
const build = await getPercyBuildForBranch(branchName);
const reviewState = build.attributes['review-state'];
const nbDiffs = build.attributes['total-comparisons-diff'];

log(`Build is in state ${reviewState} with ${nbDiffs} diffs`);
if (reviewState !== 'approved' || !nbDiffs) {
log(`No diffs requiring updates`);
throw Error();
return false;
}

const snapshots = await percyApiCall(
build.relationships.snapshots.links.related,
);

const include = snapshots.data
.filter(
({attributes}) => attributes['review-state-reason'] === 'user_approved',
)
.map(({attributes: {name}}) => `^${name}$`);

fs.writeFileSync(`./${CONFIG_FILE}`, JSON.stringify({include}));

return true;
}

// this script fails if updates are required
const headRefName = process.argv[2];
const project = process.argv[3];
checkIfBaselineUpdatesRequired(headRefName, project)
.then(() => process.exit(1))
.catch(() => process.exit(0));
module.exports = {run};
5 changes: 5 additions & 0 deletions scripts/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
name: 'scripts',
displayName: 'NewsKit Scripts',
testRegex: '(.|-)test\\.js$',
};

0 comments on commit fd4d458

Please sign in to comment.