|
1 | 1 | const { execSync } = require('child_process'); |
2 | | -const { createHash } = require('crypto'); |
3 | | -const globby = require('globby'); |
4 | | -const { dirname, join } = require('path'); |
5 | 2 |
|
6 | | -const cwd = join(__dirname, '..'); |
7 | | -const paths = globby.sync(['suites/**/docker-compose.yml'], { cwd }).map(path => join(cwd, dirname(path))); |
8 | | - |
9 | | -// Must stay in sync with `runDockerCompose` in utils/runner/createRunner.ts: |
10 | | -// the runner starts each suite under a unique, path-derived project name, so we |
11 | | -// have to target the same name here or the teardown misses the containers. |
12 | | -const projectNameFor = suiteDir => `sentry-it-${createHash('sha1').update(suiteDir).digest('hex').slice(0, 12)}`; |
| 3 | +// The runner (utils/runner/createRunner.ts) starts each suite's docker compose |
| 4 | +// stack under a project name prefixed with `sentry-it-`, derived by hashing the |
| 5 | +// working directory. Some suites (e.g. the Prisma tests) run from a temporary |
| 6 | +// directory whose path — and therefore whose derived project name — isn't known |
| 7 | +// ahead of time and no longer exists on disk by the time this script runs (the |
| 8 | +// `clean` npm script removes `tmp_*` dirs first). Reconstructing project names |
| 9 | +// from compose file paths therefore misses those stacks and leaks containers. |
| 10 | +// |
| 11 | +// Instead, ask Docker for every `sentry-it-*` project it still knows about and |
| 12 | +// tear those down by name. `docker compose -p <name> down` operates purely from |
| 13 | +// the containers' labels, so it succeeds even when the original compose file is |
| 14 | +// gone. |
| 15 | +const PROJECT_PREFIX = 'sentry-it-'; |
13 | 16 |
|
14 | 17 | // eslint-disable-next-line no-console |
15 | 18 | console.log('Cleaning up docker containers and volumes...'); |
16 | 19 |
|
17 | | -for (const path of paths) { |
| 20 | +function listSentryProjects() { |
| 21 | + let output; |
| 22 | + try { |
| 23 | + output = execSync('docker compose ls --all --format json', { encoding: 'utf8' }); |
| 24 | + } catch { |
| 25 | + return []; |
| 26 | + } |
| 27 | + |
| 28 | + let projects; |
| 29 | + try { |
| 30 | + projects = JSON.parse(output); |
| 31 | + } catch { |
| 32 | + return []; |
| 33 | + } |
| 34 | + |
| 35 | + if (!Array.isArray(projects)) { |
| 36 | + return []; |
| 37 | + } |
| 38 | + |
| 39 | + return projects |
| 40 | + .map(project => project && project.Name) |
| 41 | + .filter(name => typeof name === 'string' && name.startsWith(PROJECT_PREFIX)); |
| 42 | +} |
| 43 | + |
| 44 | +for (const name of listSentryProjects()) { |
18 | 45 | try { |
19 | 46 | // eslint-disable-next-line no-console |
20 | | - console.log(`docker compose down @ ${path}`); |
21 | | - execSync(`docker compose -p ${projectNameFor(path)} down --volumes`, { stdio: 'inherit', cwd: path }); |
| 47 | + console.log(`docker compose -p ${name} down --volumes`); |
| 48 | + execSync(`docker compose -p ${name} down --volumes`, { stdio: 'inherit' }); |
22 | 49 | } catch { |
23 | 50 | // |
24 | 51 | } |
|
0 commit comments