Skip to content

Commit

Permalink
feat: В генерируемые GitHub Actions добавлены настройки для запуска т…
Browse files Browse the repository at this point in the history
…естов из Allure TestOps
  • Loading branch information
verdel authored and tsvetta committed Mar 31, 2022
1 parent 92bf9ef commit 31b000e
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 64 deletions.
176 changes: 119 additions & 57 deletions modules/codecept/src/commands/run/generate-github-workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,12 @@ const {
getProjectRootDir,
createWorkflow,
getGitHubBrowserSecretEnv,
allureJobUidStep,
getGitHubEnv,
getGitHubEnvInputs,
allurectlWatch,
} = require('@csssr/e2e-tools/utils')

function getTestFilePrettyName(testFile) {
return testFile.replace(/\.test\.[jt]s$/, '')
}

function getJobName(testFile) {
const hash = crypto.createHash('sha256').update(testFile, 'utf8').digest('hex')
return `run-test-${hash}`
}

function generateGitHubWorkflow() {
const config = getConfig()
const codeceptConfig = config.tools['@csssr/e2e-tools-codecept']
Expand All @@ -35,50 +30,48 @@ function generateGitHubWorkflow() {
}

const githubSecretsEnv = getGitHubBrowserSecretEnv(codeceptConfig.browsers)
const testFiles = glob.sync('**/*.test.{js,ts}', {
cwd: path.join(getTestsRootDir(), 'codecept/tests'),
})

const defaultRemoteBrowser = Object.entries(codeceptConfig.browsers)
.filter(([_, cfg]) => cfg.remote)
.map(([browserName]) => browserName)[0]

function getTestRunJob(testFile, config) {
const name = getTestFilePrettyName(testFile)
const command = `yarn et codecept:run --browser \${{ github.event.inputs.browserName }} --test 'tests/${testFile}'`
function slackMessage(status) {
function byStatus(success, failure) {
return status === 'success' ? success : failure
}

return {
name,
if: `github.event.inputs.${getJobName(testFile)} == 'true'`,
'runs-on': ['self-hosted', 'e2e-tests'],
'timeout-minutes': 30,
steps: [
{
uses: 'actions/checkout@v2',
with: {
lfs: true,
},
},
{
run: 'yarn install --frozen-lockfile',
'working-directory': 'e2e-tests',
},
config.allure?.projectId && downloadAllurectlStep(),
{
run: command,
'working-directory': 'e2e-tests',
env: {
...githubSecretsEnv,
LAUNCH_URL: '${{ github.event.inputs.launchUrl }}',
...(config.allure?.projectId && { ENABLE_ALLURE_REPORT: 'true' }),
...(config.allure?.projectId && allureEnv(config, name, command)),
},
},
config.allure?.projectId && allurectlUploadStep(config, name, command),
].filter(Boolean),
'slack-bot-user-oauth-access-token': '${{ secrets.SLACK_SEND_MESSAGE_TOKEN }}',
'slack-channel': codeceptConfig.githubActions?.slackChannel,
'slack-text': [
byStatus(
':approved: *Тесты прошли успешно*',
':fire: *${{ steps.allure.outputs.report-failed-percentage }}% (${{ steps.allure.outputs.report-failed-total }}) тестов упало*'
),
'',
`Название: Run tests`,
'URL: ${{ github.event.inputs.launchUrl }}',
'Команда для запуска:',
'```',
'yarn et codecept:run --browser ${{ github.event.inputs.browserName }}',
'```',
'',
'*Allure отчёт*: ${{ steps.allure.outputs.report-link }}',
'',
'${{ steps.allure.outputs.report-summary }}',
'',
'Логи: https://github.com/${{ github.repository }}/runs/${{ steps.query-jobs.outputs.result }}?check_suite_focus=true',
'',
`https://s.csssr.ru/U09LGPMEU/${byStatus(
'20200731115845',
'20200731115800'
)}.jpg?run=\${{ github.run_id }}`,
].join('\n'),
}
}

const name = 'Run CodeceptJS e2e tests'

const workflowContent = {
name: 'Run CodeceptJS e2e tests',
concurrency: 'e2e-tests',
Expand All @@ -95,17 +88,13 @@ function generateGitHubWorkflow() {
default: defaultRemoteBrowser,
required: true,
},

...Object.fromEntries(
testFiles.map((testFile) => [
getJobName(testFile),
{
description: `Запустить тест «${getTestFilePrettyName(testFile)}»`,
required: false,
default: 'true',
},
])
),
...(codeceptConfig.allureTestOpsJobs?.enabled && {
ALLURE_JOB_RUN_ID: {
description: 'Inner parameter for Allure TestOps',
required: false,
},
}),
...getGitHubEnvInputs(config.env),
},
},
},
Expand All @@ -121,9 +110,82 @@ function generateGitHubWorkflow() {
'security-events': 'none',
statuses: 'none',
},
jobs: Object.fromEntries(
testFiles.map((testFile) => [getJobName(testFile), getTestRunJob(testFile, config)])
),
jobs: {
'run-tests': {
name: 'Run tests',
'runs-on': ['self-hosted', 'e2e-tests'],
'timeout-minutes': 90,
steps: [
{
uses: 'actions/checkout@v2',
with: {
lfs: true,
},
},
config.allure?.projectId && allureJobUidStep(),
{
run: 'yarn install --frozen-lockfile',
'working-directory': 'e2e-tests',
},
config.allure?.projectId && downloadAllurectlStep(),
{
run: allurectlWatch(
config,
`yarn et codecept:run --browser \${{ github.event.inputs.browserName }}`
),
'working-directory': 'e2e-tests',
env: {
...getGitHubEnv(config.env),
...githubSecretsEnv,
LAUNCH_URL: '${{ github.event.inputs.launchUrl }}',
...(config.allure?.projectId && { ENABLE_ALLURE_REPORT: 'true' }),
...(config.allure?.projectId &&
allureEnv(
config,
`${name} in \${{ github.event.inputs.browserName }}`,
'codecept',
codeceptConfig.allureTestOpsJobs?.enabled
)),
},
},
codeceptConfig.githubActions?.slackChannel && {
if: 'always()',
uses: 'actions/github-script@v4',
id: 'query-jobs',
with: {
script: [
'const result = await github.actions.listJobsForWorkflowRun({',
' owner: context.repo.owner,',
' repo: context.repo.repo,',
' run_id: ${{ github.run_id }},',
'})',
'return result.data.jobs[0].id',
].join('\n'),
'result-encoding': 'string',
},
},
codeceptConfig.githubActions?.slackChannel && {
if: 'failure()',
name: 'Send failure to Slack',
uses: 'archive/github-actions-slack@27663f2377ce6f86d7fca5b8056e6b977f03b5c9',
with: slackMessage('failure'),
},
codeceptConfig.githubActions?.slackChannel && {
if: 'success()',
name: 'Send success to Slack',
uses: 'archive/github-actions-slack@27663f2377ce6f86d7fca5b8056e6b977f03b5c9',
with: slackMessage('success'),
},
allurectlUploadStep(
config,
name,
'codecept',
'',
codeceptConfig.allureTestOpsJobs?.enabled
),
].filter(Boolean),
},
},
}

createWorkflow(githubWorkflowPath, workflowContent)
Expand Down
23 changes: 21 additions & 2 deletions modules/nightwatch/src/commands/generate-github-workflow.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ const {
allurectlUploadStep,
allureEnv,
downloadAllurectlStep,
allureJobUidStep,
getGitHubEnv,
getGitHubEnvInputs,
} = require('@csssr/e2e-tools/utils')

function generateGitHubWorkflow() {
Expand Down Expand Up @@ -87,6 +90,13 @@ function generateGitHubWorkflow() {
default: 'true',
required: true,
},
...(nightwatchConfig.allureTestOpsJobs?.enabled && {
ALLURE_JOB_RUN_ID: {
description: 'Inner parameter for Allure TestOps',
required: false,
},
}),
...getGitHubEnvInputs(config.env),
},
},
},
Expand Down Expand Up @@ -114,6 +124,7 @@ function generateGitHubWorkflow() {
lfs: true,
},
},
config.allure?.projectId && allureJobUidStep(),
{
run: 'yarn install --frozen-lockfile',
'working-directory': 'e2e-tests',
Expand All @@ -126,13 +137,15 @@ function generateGitHubWorkflow() {
),
'working-directory': 'e2e-tests',
env: {
...getGitHubEnv(config.env),
...githubSecretsEnv,
LAUNCH_URL: '${{ github.event.inputs.launchUrl }}',
ENABLE_ALLURE_REPORT: 'true',
...allureEnv(
config,
`${name} in \${{ github.event.inputs.browserName }}`,
'nightwatch'
'nightwatch',
nightwatchConfig.allureTestOpsJobs?.enabled
),
},
},
Expand Down Expand Up @@ -180,7 +193,13 @@ function generateGitHubWorkflow() {
uses: 'archive/github-actions-slack@27663f2377ce6f86d7fca5b8056e6b977f03b5c9',
with: slackMessage('success'),
},
allurectlUploadStep(config, name, 'nightwatch'),
allurectlUploadStep(
config,
name,
'nightwatch',
'',
nightwatchConfig.allureTestOpsJobs?.enabled
),
].filter(Boolean),
},
},
Expand Down
2 changes: 2 additions & 0 deletions modules/tools/src/commands/generate-periodic-runs.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
allurectlUploadStep,
allureEnv,
downloadAllurectlStep,
allureJobUidStep,
} = require('../utils')
const templateContext = {
url: '${{ github.event.deployment_status.environment_url }}',
Expand Down Expand Up @@ -146,6 +147,7 @@ function generatePeriodicRunWorkflow({ url, command, run, id, config }) {
'timeout-minutes': 90,
steps: [
...getCheckoutSteps(run),
config.allure?.projectId && allureJobUidStep(),
{
run: 'yarn install --frozen-lockfile',
'working-directory': 'e2e-tests',
Expand Down
63 changes: 58 additions & 5 deletions modules/tools/src/utils/allure.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function allurectlWatch(config, command) {
: command
}

function allurectlUploadStep(config, name, command, type) {
function allurectlUploadStep(config, name, command, type, allureTestOpsJobs) {
const allureLaunchName =
type === 'periodic' ? name : `${name} in \${{ github.event.inputs.browserName }}`
return (
Expand All @@ -15,7 +15,7 @@ function allurectlUploadStep(config, name, command, type) {
'working-directory': 'e2e-tests',
run: `./allurectl upload ${resultsDirectory(command)}`,
env: {
...allureEnv(config, allureLaunchName, command),
...allureEnv(config, allureLaunchName, command, allureTestOpsJobs),
},
}
)
Expand All @@ -25,16 +25,34 @@ function resultsDirectory(command) {
return `${command.includes('nightwatch') ? 'nightwatch' : 'codecept'}/report/allure-reports/`
}

function allureEnv(config, name, command) {
function allureEnv(config, name, command, allureTestOpsJobs) {
function getGitHubEnv(env) {
return Object.entries(env || {}).reduce((acc, [envName, env]) => {
return {
...acc,
[envName]: `\${{ github.event.inputs.${envName} }}`,
}
}, {})
}

return (
config.allure?.projectId && {
ALLURE_ENDPOINT: '${{ secrets.ALLURE_ENDPOINT }}',
ALLURE_TOKEN: '${{ secrets.ALLURE_TOKEN }}',
ALLURE_PROJECT_ID: config.allure?.projectId,
ALLURE_JOB_UID: '${{ github.run_id }}',
ALLURE_JOB_UID: '${{steps.allure-job-uid.outputs.result}}',
ALLURE_CI_TYPE: 'github',
ALLURE_LAUNCH_NAME: name,
ALLURE_RESULTS: resultsDirectory(command),
...(allureTestOpsJobs && {
ALLURE_JOB_RUN_ID: '${{ github.event.inputs.ALLURE_JOB_RUN_ID }}',
launchUrl: '${{ github.event.inputs.launchUrl }}',
browserName: '${{ github.event.inputs.browserName }}',
...(command.includes('nightwatch') && {
checkScreenshots: '${{ github.event.inputs.checkScreenshots }}',
}),
...getGitHubEnv(config.env),
}),
}
)
}
Expand All @@ -50,4 +68,39 @@ function downloadAllurectlStep() {
}
}

module.exports = { allurectlWatch, allurectlUploadStep, allureEnv, downloadAllurectlStep }
function allureJobUidStep() {
function deindent(s) {
const lines = s.split('\n').filter((line, index, lines) => {
const isFirstOrLastLine = index === 0 || index === lines.length - 1
return !(isFirstOrLastLine && line.trim() === '')
})

const indents = lines.filter(Boolean).map((line) => line.length - line.trimLeft().length)
const minIndent = Math.min(...indents)
const linesWithoutIndent = lines.map((line) => (line[0] === ' ' ? line.slice(minIndent) : line))
return linesWithoutIndent.join('\n')
}

return {
uses: 'actions/github-script@v6',
id: 'allure-job-uid',
with: {
'result-encoding': 'string',
script: deindent(`
const result = await github.rest.actions.getWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId,
});
return \`\${context.repo.owner}/\${context.repo.repo}/actions/workflows/\${result.data.workflow_id}\``),
},
}
}

module.exports = {
allurectlWatch,
allurectlUploadStep,
allureEnv,
downloadAllurectlStep,
allureJobUidStep,
}
Loading

0 comments on commit 31b000e

Please sign in to comment.