Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
Added tests for `deployBlocker` workflow

See: #13604
  • Loading branch information
radoslawkrzemien committed Jun 30, 2023
1 parent 6fc2a66 commit 1894bc2
Show file tree
Hide file tree
Showing 7 changed files with 408 additions and 33 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/deployBlocker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ jobs:
if: ${{ github.event.label.name == 'DeployBlockerCash' }}

steps:
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
- name: Checkout
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
Expand Down Expand Up @@ -64,7 +65,8 @@ jobs:
2. Find someone who can quickly fix the issue.
3. Fix the issue yourself.
- if: ${{ failure() }}
- name: Announce failed workflow in Slack
if: ${{ failure() }}
uses: Expensify/App/.github/actions/composite/announceFailedWorkflowInSlack@main
with:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
105 changes: 105 additions & 0 deletions workflow_tests/assertions/deployBlockerAssertions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
const utils = require('../utils/utils');

const assertDeployBlockerJobExecuted = (workflowResult, issueTitle, issueNumber, didExecute = true, isSuccessful = true) => {
const steps = [
utils.getStepAssertion(
'Checkout',
true,
null,
'DEPLOYBLOCKER',
'Checkout',
[{key: 'fetch-depth', value: '0'}, {key: 'token', value: '***'}],
[],
),
utils.getStepAssertion(
'Get URL, title, & number of new deploy blocker (issue)',
true,
null,
'DEPLOYBLOCKER',
'Get URL, title and number of new deploy blocker - issue',
[],
[{key: 'TITLE', value: issueTitle}],
),
utils.getStepAssertion(
'Update StagingDeployCash with new deploy blocker',
true,
null,
'DEPLOYBLOCKER',
'Update StagingDeployCash with new deploy blocker',
[{key: 'GITHUB_TOKEN', value: '***'}],
[],
),
utils.getStepAssertion(
'Give the issue/PR the Hourly, Engineering labels',
true,
null,
'DEPLOYBLOCKER',
'Give the issue/PR the Hourly, Engineering labels',
[{key: 'add-labels', value: 'Hourly, Engineering'}, {key: 'remove-labels', value: 'Daily, Weekly, Monthly'}],
[],
),
utils.getStepAssertion(
'Comment on deferred PR',
true,
null,
'DEPLOYBLOCKER',
'Comment on deferred PR',
[{key: 'github_token', value: '***'}, {key: 'number', value: issueNumber}],
[],
),
];

for (const expectedStep of steps) {
if (didExecute) {
if (isSuccessful) {
expect(workflowResult).toEqual(expect.arrayContaining([expectedStep]));
}
} else {
expect(workflowResult).not.toEqual(expect.arrayContaining([expectedStep]));
}
}

const successSteps = [
utils.getStepAssertion(
'Post the issue in the #expensify-open-source slack room',
true,
null,
'DEPLOYBLOCKER',
'Post the issue in the expensify-open-source slack room',
[{key: 'status', value: 'custom'}],
[{key: 'GITHUB_TOKEN', value: '***'}, {key: 'SLACK_WEBHOOK_URL', value: '***'}],
),
];

for (const step of successSteps) {
if (didExecute && isSuccessful) {
expect(workflowResult).toEqual(expect.arrayContaining([step]));
} else {
expect(workflowResult).not.toEqual(expect.arrayContaining([step]));
}
}

const failedSteps = [
utils.getStepAssertion(
'Announce failed workflow in Slack',
true,
null,
'DEPLOYBLOCKER',
'Announce failed workflow in Slack',
[{key: 'SLACK_WEBHOOK', value: '***'}],
[],
),
];

for (const step of failedSteps) {
if (didExecute && !isSuccessful) {
expect(workflowResult).toEqual(expect.arrayContaining([step]));
} else {
expect(workflowResult).not.toEqual(expect.arrayContaining([step]));
}
}
};

module.exports = {
assertDeployBlockerJobExecuted,
};
2 changes: 1 addition & 1 deletion workflow_tests/createNewVersion.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ describe('test workflow createNewVersion', () => {
act = utils.setJobRunners(act, {createNewVersion: 'ubuntu-latest'}, workflowPath);
const testMockSteps = {
validateActor: mocks.CREATENEWVERSION__VALIDATEACTOR__ADMIN__STEP_MOCKS,
createNewVersion: JSON.parse(JSON.stringify(mocks.CREATENEWVERSION__CREATENEWVERSION__STEP_MOCKS)),
createNewVersion: utils.deepCopy(mocks.CREATENEWVERSION__CREATENEWVERSION__STEP_MOCKS),
};
testMockSteps.createNewVersion[5] = utils.getMockStep(
'Commit new version',
Expand Down
163 changes: 163 additions & 0 deletions workflow_tests/deployBlocker.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
const path = require('path');
const kieMockGithub = require('@kie/mock-github');
const utils = require('./utils/utils');
const assertions = require('./assertions/deployBlockerAssertions');
const mocks = require('./mocks/deployBlockerMocks');
const eAct = require('./utils/ExtendedAct');

jest.setTimeout(60 * 1000);
let mockGithub;
const FILES_TO_COPY_INTO_TEST_REPO = [
{
src: path.resolve(__dirname, '..', '.github', 'actions'),
dest: '.github/actions',
},
{
src: path.resolve(__dirname, '..', '.github', 'libs'),
dest: '.github/libs',
},
{
src: path.resolve(__dirname, '..', '.github', 'scripts'),
dest: '.github/scripts',
},
{
src: path.resolve(__dirname, '..', '.github', 'workflows', 'deployBlocker.yml'),
dest: '.github/workflows/deployBlocker.yml',
},
];

describe('test workflow deployBlocker', () => {
const githubToken = 'dummy_github_token';
const actor = 'Dummy Author';
const secrets = {
OS_BOTIFY_TOKEN: 'dummy_osbotify_token',
SLACK_WEBHOOK: 'dummy_slack_webhook',
};
beforeEach(async () => {
// create a local repository and copy required files
mockGithub = new kieMockGithub.MockGithub({
repo: {
testDeployBlockerWorkflowRepo: {
files: FILES_TO_COPY_INTO_TEST_REPO,

// if any branches besides main are need add: pushedBranches: ['staging', 'production'],
},
},
});

await mockGithub.setup();
});

afterEach(async () => {
await mockGithub.teardown();
});
describe('issue labeled', () => {
const event = 'issues';
const eventOptions = {
action: 'labeled',
label: {
name: 'DeployBlockerCash',
},
issue: {
title: 'Labeled issue title',
number: '1234',
html_url: 'http://issue.html.url',
},
};
describe('label is DeployBlockerCash', () => {
const testEventOptions = utils.deepCopy(eventOptions);
testEventOptions.label = {name: 'DeployBlockerCash'};
it('runs the workflow and announces success on Slack', async () => {
const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deployBlocker.yml');
let act = new eAct.ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
act,
event,
testEventOptions,
secrets,
githubToken,
{},
{},
);
const testMockSteps = {
deployBlocker: mocks.DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS,
};
const result = await act
.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows'),
mockSteps: testMockSteps,
actor,
});

assertions.assertDeployBlockerJobExecuted(result, 'Labeled issue title', '1234');
});
describe('one step fails', () => {
it('announces failure on Slack', async () => {
const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deployBlocker.yml');
let act = new eAct.ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
act,
event,
testEventOptions,
secrets,
githubToken,
{},
{},
);
const testMockSteps = {
deployBlocker: utils.deepCopy(mocks.DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS),
};
testMockSteps.deployBlocker[2] = utils.getMockStep(
'Update StagingDeployCash with new deploy blocker',
'Update StagingDeployCash with new deploy blocker',
'DEPLOYBLOCKER',
['GITHUB_TOKEN'],
[],
{},
{},
false,
);
const result = await act
.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows'),
mockSteps: testMockSteps,
actor,
});

assertions.assertDeployBlockerJobExecuted(result, 'Labeled issue title', '1234', true, false);
});
});
});
describe('label is different', () => {
const testEventOptions = utils.deepCopy(eventOptions);
testEventOptions.label = {name: 'Different Label'};
it('does not run workflow', async () => {
const repoPath = mockGithub.repo.getPath('testDeployBlockerWorkflowRepo') || '';
const workflowPath = path.join(repoPath, '.github', 'workflows', 'deployBlocker.yml');
let act = new eAct.ExtendedAct(repoPath, workflowPath);
act = utils.setUpActParams(
act,
event,
testEventOptions,
secrets,
githubToken,
{},
{},
);
const testMockSteps = {
deployBlocker: mocks.DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS,
};
const result = await act
.runEvent(event, {
workflowFile: path.join(repoPath, '.github', 'workflows'),
mockSteps: testMockSteps,
actor,
});

assertions.assertDeployBlockerJobExecuted(result, '', '', false);
});
});
});
});
71 changes: 71 additions & 0 deletions workflow_tests/mocks/deployBlockerMocks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const utils = require('../utils/utils');

// deployblocker
const DEPLOYBLOCKER__DEPLOYBLOCKER__CHECKOUT__STEP_MOCK = utils.getMockStep(
'Checkout',
'Checkout',
'DEPLOYBLOCKER',
['fetch-depth', 'token'],
[],
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__GET_URL_TITLE_AND_NUMBER_OF_NEW_DEPLOY_BLOCKER_ISSUE__STEP_MOCK = utils.getMockStep(
'Get URL, title, & number of new deploy blocker (issue)',
'Get URL, title and number of new deploy blocker - issue',
'DEPLOYBLOCKER',
[],
['TITLE'],
{},
{
DEPLOY_BLOCKER_URL: '${{ github.event.issue.html_url }}',
DEPLOY_BLOCKER_NUMBER: '${{ github.event.issue.number }}',
DEPLOY_BLOCKER_TITLE: '${{ github.event.issue.title }}',
},
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__UPDATE_STAGINGDEPLOYCASH_WITH_NEW_DEPLOY_BLOCKER__STEP_MOCK = utils.getMockStep(
'Update StagingDeployCash with new deploy blocker',
'Update StagingDeployCash with new deploy blocker',
'DEPLOYBLOCKER',
['GITHUB_TOKEN'],
[],
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__GIVE_THE_ISSUE_OR_PR_THE_HOURLY_ENGINEERING_LABELS__STEP_MOCK = utils.getMockStep(
'Give the issue/PR the Hourly, Engineering labels',
'Give the issue/PR the Hourly, Engineering labels',
'DEPLOYBLOCKER',
['add-labels', 'remove-labels'],
[],
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__POST_THE_ISSUE_IN_THE_EXPENSIFY_OPEN_SOURCE_SLACK_ROOM__STEP_MOCK = utils.getMockStep(
'Post the issue in the #expensify-open-source slack room',
'Post the issue in the expensify-open-source slack room',
'DEPLOYBLOCKER',
['status'],
['GITHUB_TOKEN', 'SLACK_WEBHOOK_URL'],
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__COMMENT_ON_DEFERRED_PR__STEP_MOCK = utils.getMockStep(
'Comment on deferred PR',
'Comment on deferred PR',
'DEPLOYBLOCKER',
['github_token', 'number'],
[],
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK = utils.getMockStep(
'Announce failed workflow in Slack',
'Announce failed workflow in Slack',
'DEPLOYBLOCKER',
['SLACK_WEBHOOK'],
[],
);
const DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS = [
DEPLOYBLOCKER__DEPLOYBLOCKER__CHECKOUT__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__GET_URL_TITLE_AND_NUMBER_OF_NEW_DEPLOY_BLOCKER_ISSUE__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__UPDATE_STAGINGDEPLOYCASH_WITH_NEW_DEPLOY_BLOCKER__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__GIVE_THE_ISSUE_OR_PR_THE_HOURLY_ENGINEERING_LABELS__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__POST_THE_ISSUE_IN_THE_EXPENSIFY_OPEN_SOURCE_SLACK_ROOM__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__COMMENT_ON_DEFERRED_PR__STEP_MOCK,
DEPLOYBLOCKER__DEPLOYBLOCKER__ANNOUNCE_FAILED_WORKFLOW_IN_SLACK__STEP_MOCK,
];

module.exports = {
DEPLOYBLOCKER__DEPLOYBLOCKER__STEP_MOCKS,
};
Loading

0 comments on commit 1894bc2

Please sign in to comment.