diff --git a/.circleci/config.yml b/.circleci/config.yml index 9ec5895ab7..a52d4fb5d7 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,31 +22,6 @@ integration_steps: &integration_steps - store_test_results: path: junit -services_steps: &services_steps - steps: - - checkout - - - run: - name: Install dependencies - command: | - npm ci - environment: - CYPRESS_INSTALL_BINARY: 0 - - - run: - name: Identify services tagged in the PR title - command: npm run test:services:pr:prepare - - - run: - name: Run tests for tagged services - environment: - mocha_reporter: mocha-junit-reporter - MOCHA_FILE: junit/services/results.xml - command: RETRY_COUNT=3 npm run test:services:pr:run - - - store_test_results: - path: junit - jobs: integration: docker: @@ -122,20 +97,6 @@ jobs: when: always command: npm run build - services: - docker: - - image: cimg/node:16.15 - - <<: *services_steps - - services@node-17: - docker: - - image: cimg/node:17.9 - environment: - NPM_CONFIG_ENGINE_STRICT: 'false' - - <<: *services_steps - e2e: docker: - image: cypress/base:16.14.0 @@ -193,18 +154,6 @@ workflows: filters: branches: ignore: gh-pages - - services: - filters: - branches: - ignore: - - master - - gh-pages - - services@node-17: - filters: - branches: - ignore: - - master - - gh-pages - danger: filters: branches: @@ -225,18 +174,6 @@ workflows: # - frontend: # requires: # - npm-install - # - services: - # requires: - # - npm-install - # filters: - # branches: - # ignore: master - # - services@node-latest: - # requires: - # - npm-install - # filters: - # branches: - # ignore: master # - danger: # requires: # - npm-install diff --git a/.github/actions/service-tests/action.yml b/.github/actions/service-tests/action.yml new file mode 100644 index 0000000000..f532c33bef --- /dev/null +++ b/.github/actions/service-tests/action.yml @@ -0,0 +1,22 @@ +name: 'Service tests' +description: 'Run tests for selected services' +runs: + using: 'composite' + steps: + - name: Derive list of service tests to run + if: always() + run: npm run test:services:pr:prepare ${{ github.event.pull_request.title }} + shell: bash + + - name: Run service tests + if: always() + run: npm run test:services:pr:run -- --reporter json --reporter-option 'output=reports/service-tests.json' + shell: bash + env: + RETRY_COUNT: 3 + + - name: Write Markdown Summary + if: always() + run: | + node scripts/mocha2md.js Services reports/service-tests.json >> $GITHUB_STEP_SUMMARY + shell: bash diff --git a/.github/workflows/test-services-17.yml b/.github/workflows/test-services-17.yml new file mode 100644 index 0000000000..10f8ff0043 --- /dev/null +++ b/.github/workflows/test-services-17.yml @@ -0,0 +1,20 @@ +name: Main +on: + pull_request: + +jobs: + test-services-17: + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + node-version: 17 + env: + NPM_CONFIG_ENGINE_STRICT: 'false' + + - name: Service tests + uses: ./.github/actions/service-tests diff --git a/.github/workflows/test-services.yml b/.github/workflows/test-services.yml new file mode 100644 index 0000000000..779e52d874 --- /dev/null +++ b/.github/workflows/test-services.yml @@ -0,0 +1,18 @@ +name: Main +on: + pull_request: + +jobs: + test-services: + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup + with: + node-version: 16 + + - name: Service tests + uses: ./.github/actions/service-tests diff --git a/core/service-test-runner/infer-pull-request.js b/core/service-test-runner/infer-pull-request.js deleted file mode 100644 index 699abb5bf5..0000000000 --- a/core/service-test-runner/infer-pull-request.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @module - */ - -import { URL, format as urlFormat } from 'url' - -function formatSlug(owner, repo, pullRequest) { - return `${owner}/${repo}#${pullRequest}` -} - -function parseGithubPullRequestUrl(url, options = {}) { - const { verifyBaseUrl } = options - - const parsed = new URL(url) - const components = parsed.pathname.substr(1).split('/') - if (components[2] !== 'pull' || components.length !== 4) { - throw Error(`Invalid GitHub pull request URL: ${url}`) - } - const [owner, repo, , pullRequest] = components - - parsed.pathname = '' - const baseUrl = urlFormat(parsed, { - auth: false, - fragment: false, - search: false, - }).replace(/\/$/, '') - - if (verifyBaseUrl && baseUrl !== verifyBaseUrl) { - throw Error(`Expected base URL to be ${verifyBaseUrl} but got ${baseUrl}`) - } - - return { - baseUrl, - owner, - repo, - pullRequest: +pullRequest, - slug: formatSlug(owner, repo, pullRequest), - } -} - -function parseGithubRepoSlug(slug) { - const components = slug.split('/') - if (components.length !== 2) { - throw Error(`Invalid GitHub repo slug: ${slug}`) - } - const [owner, repo] = components - return { owner, repo } -} - -function _inferPullRequestFromTravisEnv(env) { - const { owner, repo } = parseGithubRepoSlug(env.TRAVIS_REPO_SLUG) - const pullRequest = +env.TRAVIS_PULL_REQUEST - return { - owner, - repo, - pullRequest, - slug: formatSlug(owner, repo, pullRequest), - } -} - -function _inferPullRequestFromCircleEnv(env) { - return parseGithubPullRequestUrl( - env.CI_PULL_REQUEST || env.CIRCLE_PULL_REQUEST - ) -} - -/** - * When called inside a CI build, infer the details - * of a pull request from the environment variables. - * - * @param {object} [env=process.env] Environment variables - * @returns {module:core/service-test-runner/infer-pull-request~PullRequest} - * Pull Request - */ -function inferPullRequest(env = process.env) { - if (env.TRAVIS) { - return _inferPullRequestFromTravisEnv(env) - } else if (env.CIRCLECI) { - return _inferPullRequestFromCircleEnv(env) - } else if (env.CI) { - throw Error( - 'Unsupported CI system. Unable to obtain pull request information from the environment.' - ) - } else { - throw Error( - 'Unable to obtain pull request information from the environment. Is this running in CI?' - ) - } -} - -/** - * Pull Request - * - * @typedef PullRequest - * @property {string} pr.baseUrl (returned for travis CI only) - * @property {string} owner - * @property {string} repo - * @property {string} pullRequest PR/issue number - * @property {string} slug owner/repo/#pullRequest - */ - -export { parseGithubPullRequestUrl, parseGithubRepoSlug, inferPullRequest } diff --git a/core/service-test-runner/infer-pull-request.spec.js b/core/service-test-runner/infer-pull-request.spec.js deleted file mode 100644 index c2050d533e..0000000000 --- a/core/service-test-runner/infer-pull-request.spec.js +++ /dev/null @@ -1,48 +0,0 @@ -import { test, given, forCases } from 'sazerac' -import { - parseGithubPullRequestUrl, - inferPullRequest, -} from './infer-pull-request.js' - -describe('Pull request inference', function () { - test(parseGithubPullRequestUrl, () => { - forCases([ - given('https://github.com/badges/shields/pull/1234'), - given('https://github.com/badges/shields/pull/1234', { - verifyBaseUrl: 'https://github.com', - }), - ]).expect({ - baseUrl: 'https://github.com', - owner: 'badges', - repo: 'shields', - pullRequest: 1234, - slug: 'badges/shields#1234', - }) - - given('https://github.com/badges/shields/pull/1234', { - verifyBaseUrl: 'https://example.com', - }).expectError( - 'Expected base URL to be https://example.com but got https://github.com' - ) - }) - - test(inferPullRequest, () => { - const expected = { - owner: 'badges', - repo: 'shields', - pullRequest: 1234, - slug: 'badges/shields#1234', - } - - given({ - CIRCLECI: '1', - CI_PULL_REQUEST: 'https://github.com/badges/shields/pull/1234', - }).expect(Object.assign({ baseUrl: 'https://github.com' }, expected)) - - given({ - TRAVIS: '1', - TRAVIS_REPO_SLUG: 'badges/shields', - TRAVIS_PULL_REQUEST: '1234', - }).expect(expected) - }) -}) diff --git a/core/service-test-runner/pull-request-services-cli.js b/core/service-test-runner/pull-request-services-cli.js index 34d8d20993..a0c307c20f 100644 --- a/core/service-test-runner/pull-request-services-cli.js +++ b/core/service-test-runner/pull-request-services-cli.js @@ -1,5 +1,5 @@ -// Infer the current PR from the Travis environment, and look for bracketed, -// space-separated service names in the pull request title. +// Derive a list of service tests to run based on +// space-separated service names in the PR title. // // Output the list of services. // @@ -8,54 +8,26 @@ // Output: // travis // sonar -// -// Example: -// -// TRAVIS=1 TRAVIS_REPO_SLUG=badges/shields TRAVIS_PULL_REQUEST=1108 npm run test:services:pr:prepare -import got from 'got' -import { inferPullRequest } from './infer-pull-request.js' import servicesForTitle from './services-for-title.js' -async function getTitle(owner, repo, pullRequest) { - const { - body: { title }, - } = await got( - `https://api.github.com/repos/${owner}/${repo}/pulls/${pullRequest}`, - { - headers: { - 'User-Agent': 'badges/shields', - Authorization: `token ${process.env.GITHUB_TOKEN}`, - }, - responseType: 'json', - } - ) - return title +let title + +try { + if (process.argv.length < 3) { + throw new Error() + } + title = process.argv[2] +} catch (e) { + console.error('Error processing arguments') + process.exit(1) } -async function main() { - const { owner, repo, pullRequest, slug } = inferPullRequest() - console.error(`PR: ${slug}`) - - const title = await getTitle(owner, repo, pullRequest) - - console.error(`Title: ${title}\n`) - const services = servicesForTitle(title) - if (services.length === 0) { - console.error('No services found. Nothing to do.') - } else { - console.error( - `Services: (${services.length} found) ${services.join(', ')}\n` - ) - console.log(services.join('\n')) - } +console.error(`Title: ${title}\n`) +const services = servicesForTitle(title) +if (services.length === 0) { + console.error('No services found. Nothing to do.') +} else { + console.error(`Services: (${services.length} found) ${services.join(', ')}\n`) + console.log(services.join('\n')) } - -;(async () => { - try { - await main() - } catch (e) { - console.error(e) - process.exit(1) - } -})()