Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions challenges/glitch-invaders/sentry.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$comment": "Public settings for live Sentry mode; none is a secret. MLH fills these in from its Sentry project: dsn from Project Settings > Client Keys (DSN), org and project from the slugs in the project's URL. While any value is still a <placeholder>, the game runs in demo mode. Live mode also needs SENTRY_AUTH_TOKEN, which the station's vault provides; never put a token here. An optional apiUrl replaces the Sentry API origin, https://sentry.io, with a subdomain of it or a loopback stand-in for tests; the token goes to no other host.",
"dsn": "<https://public-key@o0.ingest.us.sentry.io/0>",
"org": "<org-slug>",
"project": "<project-slug>"
"dsn": "https://39390e5e5e8e7a81f7013234e24343ee@o4512131379101696.ingest.us.sentry.io/4512142806941696",
"org": "major-league-hacking-xc",
"project": "glitch-invaders"
}
41 changes: 26 additions & 15 deletions test/glitch-invaders.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -497,20 +497,26 @@ function runPackageHook(packageDir, hook, env) {
}

/**
* Copy the package and fill in its `sentry.json` with live settings pointing at `apiUrl`, so the
* shipped hooks run against the stand-in. Resolves with the copy's directory, which
* Copy the package with `settings` as its `sentry.json`. Resolves with the copy's directory, which
* {@link startLivePackage} removes once its cleanup hook has run.
*/
async function makeLivePackage(apiUrl) {
async function makePackageWithSettings(settings) {
const copyRoot = await mkdtemp(path.join(os.tmpdir(), 'glitch-package-'));
const packageDir = path.join(copyRoot, 'glitch-invaders');
await cp(packageDirectory, packageDir, { recursive: true });
const settings = { dsn: LIVE_DSN, org: 'mlh', project: 'glitch-invaders', apiUrl };
await writeFile(path.join(packageDir, 'sentry.json'), `${JSON.stringify(settings)}\n`);

return packageDir;
}

/**
* Copy the package with live settings pointing at `apiUrl`, so the shipped hooks run against the
* stand-in.
*/
function makeLivePackage(apiUrl) {
return makePackageWithSettings({ dsn: LIVE_DSN, org: 'mlh', project: 'glitch-invaders', apiUrl });
}

/**
* Run the live package's setup hook in a fresh workspace with `extraEnv`, registering its cleanup
* hook. Resolves with the server's base URL, the hook's output, and the workspace.
Expand Down Expand Up @@ -1194,26 +1200,31 @@ test('setup and cleanup run standalone from the current directory with no BOOTHS
assert.equal(existsSync(path.join(workspace, '.glitch')), false);
});

test('the package names the gemini and sentry vault services and ships placeholder Sentry settings', async () => {
test('the package names the gemini and sentry vault services and ships live Sentry settings for sentry.io', async () => {
const manifest = JSON.parse(await readFile(path.join(packageDirectory, 'challenge.json'), 'utf8'));
const settings = JSON.parse(await readFile(path.join(packageDirectory, 'sentry.json'), 'utf8'));

assert.deepEqual(manifest.vault_services, ['gemini', 'sentry']);
for (const key of ['dsn', 'org', 'project']) {
assert.match(settings[key], /^<.+>$/, `${key} is not a placeholder`);
}
assert.match(settings.dsn, /^https:\/\/[0-9a-f]{32}@o\d+\.ingest\.(us\.)?sentry\.io\/\d+$/);
assert.match(settings.org, /^[a-z0-9-]+$/);
assert.match(settings.project, /^[a-z0-9-]+$/);
assert.equal(settings.apiUrl, undefined);
});

test('setup stays in demo mode with SENTRY_AUTH_TOKEN set while sentry.json holds placeholders', async (testContext) => {
const stack = await startStack(testContext, { SENTRY_AUTH_TOKEN: SENTRY_TOKEN });
const packageDir = await makePackageWithSettings({
dsn: '<https://public-key@o0.ingest.us.sentry.io/0>',
org: '<org-slug>',
project: '<project-slug>',
});
const stack = await startLivePackage(testContext, packageDir, { SENTRY_AUTH_TOKEN: SENTRY_TOKEN });

const config = await (await fetch(`${stack.url}runtime-config.json`)).json();
const page = await getRaw(stack.url, '/');
const evidence = await fetchEvidence(stack.url.replace(/\/$/, ''), 'weapon', WEAPON_EVENT_ID);
const config = await (await fetch(`${stack.base}/runtime-config.json`)).json();
const page = await getRaw(`${stack.base}/`, '/');
const evidence = await fetchEvidence(stack.base, 'weapon', WEAPON_EVENT_ID);

assert.deepEqual(config, { attemptId: stack.attemptId });
assert.equal(stack.live, false);
assert.equal(stack.note, null);
assert.deepEqual(Object.keys(config), ['attemptId']);
assert.doesNotMatch(stack.output, /live Sentry mode/);
assert.equal(page.headers['content-security-policy'], CONTENT_SECURITY_POLICY);
assert.equal(evidence.status, 404);
});
Expand Down
Loading