Skip to content

Commit bc1475a

Browse files
authored
test(e2e): Set up fake registry for E2E tests (#5806)
1 parent a5bfa80 commit bc1475a

File tree

13 files changed

+495
-1
lines changed

13 files changed

+495
-1
lines changed

.github/workflows/build.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,3 +613,35 @@ jobs:
613613
run: |
614614
cd packages/remix
615615
yarn test:integration:ci
616+
617+
job_e2e_tests:
618+
name: E2E Tests
619+
needs: [job_get_metadata, job_build]
620+
runs-on: ubuntu-latest
621+
timeout-minutes: 10
622+
continue-on-error: true
623+
steps:
624+
- name: Check out current commit (${{ needs.job_get_metadata.outputs.commit_label }})
625+
uses: actions/checkout@v2
626+
with:
627+
ref: ${{ env.HEAD_COMMIT }}
628+
- name: Set up Node
629+
uses: actions/setup-node@v1
630+
with:
631+
node-version: ${{ env.DEFAULT_NODE_VERSION }}
632+
- name: Check dependency cache
633+
uses: actions/cache@v2
634+
with:
635+
path: ${{ env.CACHED_DEPENDENCY_PATHS }}
636+
key: ${{ needs.job_build.outputs.dependency_cache_key }}
637+
- name: Check build cache
638+
uses: actions/cache@v2
639+
with:
640+
path: ${{ env.CACHED_BUILD_PATHS }}
641+
key: ${{ env.BUILD_CACHE_KEY }}
642+
- name: Run E2E tests
643+
env:
644+
E2E_TEST_PUBLISH_SCRIPT_NODE_VERSION: ${{ env.DEFAULT_NODE_VERSION }}
645+
run: |
646+
cd packages/e2e-tests
647+
yarn test:e2e

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"packages/angular",
3535
"packages/browser",
3636
"packages/core",
37+
"packages/e2e-tests",
3738
"packages/ember",
3839
"packages/eslint-config-sdk",
3940
"packages/eslint-plugin-sdk",

packages/e2e-tests/.eslintrc.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
module.exports = {
2+
env: {
3+
node: true,
4+
},
5+
extends: ['../../.eslintrc.js'],
6+
ignorePatterns: [],
7+
parserOptions: {
8+
sourceType: 'module',
9+
},
10+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# This Dockerfile exists for the purpose of using a specific node/npm version (ie. the same we use in CI) to run npm publish with
2+
ARG NODE_VERSION=16.15.1
3+
FROM node:${NODE_VERSION}
4+
5+
WORKDIR /sentry-javascript/packages/e2e-tests
6+
CMD [ "yarn", "ts-node", "publish-packages.ts" ]

packages/e2e-tests/LICENSE

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
MIT License
2+
3+
Copyright (c) 2022, Sentry
4+
All rights reserved.
5+
6+
Redistribution and use in source and binary forms, with or without
7+
modification, are permitted provided that the following conditions are met:
8+
9+
* Redistributions of source code must retain the above copyright notice, this
10+
list of conditions and the following disclaimer.
11+
12+
* Redistributions in binary form must reproduce the above copyright notice,
13+
this list of conditions and the following disclaimer in the documentation
14+
and/or other materials provided with the distribution.
15+
16+
* Neither the name of the copyright holder nor the names of its
17+
contributors may be used to endorse or promote products derived from
18+
this software without specific prior written permission.
19+
20+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

packages/e2e-tests/package.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@sentry-internal/e2e-tests",
3+
"version": "7.13.0",
4+
"license": "MIT",
5+
"engines": {
6+
"node": ">=10"
7+
},
8+
"private": true,
9+
"scripts": {
10+
"fix": "run-s fix:eslint fix:prettier",
11+
"fix:eslint": "eslint . --format stylish --fix",
12+
"fix:prettier": "prettier --config ../../.prettierrc.json --write . ",
13+
"lint": "run-s lint:prettier lint:eslint",
14+
"lint:eslint": "eslint . --cache --cache-location '../../eslintcache/' --format stylish",
15+
"lint:prettier": "prettier --config ../../.prettierrc.json --check .",
16+
"test:e2e": "run-s test:validate-configuration test:run",
17+
"test:run": "ts-node run.ts",
18+
"test:validate-configuration": "ts-node validate-verdaccio-configuration.ts"
19+
},
20+
"devDependencies": {
21+
"@types/glob": "8.0.0",
22+
"glob": "8.0.3",
23+
"ts-node": "10.9.1",
24+
"typescript": "3.8.3",
25+
"yaml": "2.1.1"
26+
}
27+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* eslint-disable no-console */
2+
import * as childProcess from 'child_process';
3+
import * as glob from 'glob';
4+
import * as path from 'path';
5+
6+
const repositoryRoot = path.resolve(__dirname, '../..');
7+
8+
// Create tarballs
9+
childProcess.execSync('yarn build:npm', { encoding: 'utf8', cwd: repositoryRoot, stdio: 'inherit' });
10+
11+
// Get absolute paths of all the packages we want to publish to the fake registry
12+
const packageTarballPaths = glob.sync('packages/*/sentry-*.tgz', {
13+
cwd: repositoryRoot,
14+
absolute: true,
15+
});
16+
17+
// Publish built packages to the fake registry
18+
packageTarballPaths.forEach(tarballPath => {
19+
// `--userconfig` flag needs to be before `publish`
20+
childProcess.execSync(`npm --userconfig ${__dirname}/test-registry.npmrc publish ${tarballPath}`, {
21+
cwd: repositoryRoot, // Can't use __dirname here because npm would try to publish `@sentry-internal/e2e-tests`
22+
encoding: 'utf8',
23+
stdio: 'inherit',
24+
});
25+
});

packages/e2e-tests/run.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/* eslint-disable no-console */
2+
import * as childProcess from 'child_process';
3+
import * as path from 'path';
4+
5+
const repositoryRoot = path.resolve(__dirname, '../..');
6+
7+
const TEST_REGISTRY_CONTAINER_NAME = 'verdaccio-e2e-test-registry';
8+
const VERDACCIO_VERSION = '5.15.3';
9+
10+
const PUBLISH_PACKAGES_DOCKER_IMAGE_NAME = 'publish-packages';
11+
12+
const publishScriptNodeVersion = process.env.E2E_TEST_PUBLISH_SCRIPT_NODE_VERSION;
13+
14+
try {
15+
// Stop test registry container (Verdaccio) if it was already running
16+
childProcess.execSync(`docker stop ${TEST_REGISTRY_CONTAINER_NAME}`, { stdio: 'ignore' });
17+
console.log('Stopped previously running test registry');
18+
} catch (e) {
19+
// Don't throw if container wasn't running
20+
}
21+
22+
// Start test registry (Verdaccio)
23+
childProcess.execSync(
24+
`docker run --detach --rm --name ${TEST_REGISTRY_CONTAINER_NAME} -p 4873:4873 -v ${__dirname}/verdaccio-config:/verdaccio/conf verdaccio/verdaccio:${VERDACCIO_VERSION}`,
25+
{ encoding: 'utf8', stdio: 'inherit' },
26+
);
27+
28+
// Build container image that is uploading our packages to fake registry with specific Node.js/npm version
29+
childProcess.execSync(
30+
`docker build --tag ${PUBLISH_PACKAGES_DOCKER_IMAGE_NAME} --file ./Dockerfile.publish-packages ${
31+
publishScriptNodeVersion ? `--build-arg NODE_VERSION=${publishScriptNodeVersion}` : ''
32+
} .`,
33+
{
34+
encoding: 'utf8',
35+
stdio: 'inherit',
36+
},
37+
);
38+
39+
// Run container that uploads our packages to fake registry
40+
childProcess.execSync(
41+
`docker run --rm -v ${repositoryRoot}:/sentry-javascript --network host ${PUBLISH_PACKAGES_DOCKER_IMAGE_NAME}`,
42+
{
43+
encoding: 'utf8',
44+
stdio: 'inherit',
45+
},
46+
);
47+
48+
// TODO: Run e2e tests here
49+
50+
// Stop test registry
51+
childProcess.execSync(`docker stop ${TEST_REGISTRY_CONTAINER_NAME}`, { encoding: 'utf8', stdio: 'ignore' });
52+
console.log('Successfully stopped test registry container'); // Output from command above is not good so we `ignore` it and emit our own
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@sentry:registry=http://localhost:4873
2+
@sentry-internal:registry=http://localhost:4873
3+
//localhost:4873/:_authToken=some-token

packages/e2e-tests/tsconfig.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"types": ["node"]
5+
}
6+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import * as assert from 'assert';
2+
import * as fs from 'fs';
3+
import * as glob from 'glob';
4+
import * as path from 'path';
5+
import * as YAML from 'yaml';
6+
7+
/*
8+
* This file is a quick automatic check to confirm that the packages in the Verdaccio configuration always match the
9+
* packages we defined in our monorepo. This is to ensure that the E2E tests do not use the packages that live on NPM
10+
* but the local ones instead.
11+
*/
12+
13+
const repositoryRoot = path.resolve(__dirname, '../..');
14+
15+
const verdaccioConfigContent = fs.readFileSync('./verdaccio-config/config.yaml', { encoding: 'utf8' });
16+
const verdaccioConfig = YAML.parse(verdaccioConfigContent);
17+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
18+
const sentryScopedPackagesInVerdaccioConfig = Object.keys(verdaccioConfig.packages).filter(packageName =>
19+
packageName.startsWith('@sentry/'),
20+
);
21+
22+
const packageJsonPaths = glob.sync('packages/*/package.json', {
23+
cwd: repositoryRoot,
24+
absolute: true,
25+
});
26+
const packageJsons = packageJsonPaths.map(packageJsonPath => require(packageJsonPath));
27+
const sentryScopedPackageNames = packageJsons
28+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
29+
.filter(packageJson => packageJson.name.startsWith('@sentry/'))
30+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
31+
.map(packageJson => packageJson.name);
32+
33+
const extraPackagesInVerdaccioConfig = sentryScopedPackagesInVerdaccioConfig.filter(
34+
x => !sentryScopedPackageNames.includes(x),
35+
);
36+
const extraPackagesInMonoRepo = sentryScopedPackageNames.filter(
37+
x => !sentryScopedPackagesInVerdaccioConfig.includes(x),
38+
);
39+
40+
assert.ok(
41+
extraPackagesInVerdaccioConfig.length === 0 && extraPackagesInMonoRepo.length === 0,
42+
`Packages in Verdaccio configuration do not match the "@sentry"-scoped packages in monorepo. Make sure they match!\nPackages missing in Verdaccio configuration: ${JSON.stringify(
43+
extraPackagesInMonoRepo,
44+
)}\nPackages missing in monorepo: ${JSON.stringify(extraPackagesInVerdaccioConfig)}`,
45+
);

0 commit comments

Comments
 (0)