| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import assert from 'node:assert/strict';
- import {
- chmodSync,
- mkdirSync,
- mkdtempSync,
- readFileSync,
- rmSync,
- writeFileSync
- } from 'node:fs';
- import os from 'node:os';
- import path from 'node:path';
- import { spawnSync } from 'node:child_process';
- import { test } from 'node:test';
- import { fileURLToPath } from 'node:url';
- const scriptPath = fileURLToPath(new URL('../scripts/deploy-remote.sh', import.meta.url));
- const canRun = process.platform !== 'win32';
- test('waits for app and postfix health before and after certificate synchronization', { skip: !canRun }, (t) => {
- const fixture = createFixture(t);
- const result = runDeploy(fixture);
- assert.equal(result.status, 0, result.stderr);
- const events = readEvents(fixture.logFile);
- assert.deepEqual(
- events.filter((event) => event.startsWith('health:') || event.startsWith('sync:')),
- [
- 'health:app-container',
- 'health:postfix-container',
- 'sync:1',
- 'health:app-container',
- 'health:postfix-container'
- ]
- );
- });
- test('reports the previous revision when deployment fails', { skip: !canRun }, (t) => {
- const fixture = createFixture(t);
- const result = runDeploy(fixture, { syncStatus: '19' });
- assert.equal(result.status, 19);
- assert.match(
- result.stderr,
- /Deployment failed\. Previous revision was previous-revision; inspect the running containers before rollback\./
- );
- const events = readEvents(fixture.logFile);
- assert.equal(events.filter((event) => event === 'sync:1').length, 1);
- assert.equal(events.filter((event) => event === 'health:app-container').length, 1);
- assert.equal(events.filter((event) => event === 'health:postfix-container').length, 1);
- });
- function createFixture(t) {
- const root = mkdtempSync(path.join(os.tmpdir(), 'mailhub-deploy-script-'));
- const fakeBin = path.join(root, 'bin');
- const remoteDir = path.join(root, 'remote');
- const remoteScriptsDir = path.join(remoteDir, 'scripts');
- const logFile = path.join(root, 'events.log');
- mkdirSync(fakeBin, { recursive: true });
- mkdirSync(remoteScriptsDir, { recursive: true });
- writeFileSync(logFile, '');
- writeExecutable(path.join(fakeBin, 'git'), `#!/bin/sh
- if [ "$1" = "remote" ] && [ "$2" = "get-url" ]; then
- printf '%s\\n' 'ssh://git.example.test/mailhub.git'
- elif [ "$1" = "status" ]; then
- :
- elif [ "$1" = "rev-parse" ] && [ "$2" = "HEAD" ]; then
- if [ "$PWD" = "$MAILHUB_DEPLOY_TEST_REMOTE_DIR" ]; then
- printf '%s\\n' 'previous-revision'
- else
- printf '%s\\n' 'pushed-revision'
- fi
- elif [ "$1" = "rev-parse" ]; then
- printf '%s\\n' 'pushed-revision'
- fi
- `);
- writeExecutable(path.join(fakeBin, 'ssh'), `#!/bin/sh
- while [ "$#" -gt 0 ]; do
- case "$1" in
- -o) shift 2 ;;
- *) break ;;
- esac
- done
- [ "$#" -gt 0 ] && shift
- [ "$#" -gt 0 ] && shift
- [ "\${1:-}" = "--" ] && shift
- exec bash -s -- "$@"
- `);
- writeExecutable(path.join(fakeBin, 'docker'), `#!/bin/sh
- if [ "$1" = "compose" ] && [ "$2" = "ps" ] && [ "\${3:-}" = "--all" ]; then
- printf '%s-container\\n' "$5"
- exit 0
- fi
- if [ "$1" = "inspect" ]; then
- container=''
- for argument in "$@"; do
- container="$argument"
- done
- printf 'health:%s\\n' "$container" >> "$MAILHUB_DEPLOY_TEST_LOG"
- printf '%s\\n' 'running healthy'
- fi
- `);
- writeExecutable(path.join(remoteScriptsDir, 'sync-tls-certificate.sh'), `#!/bin/sh
- printf 'sync:%s\\n' "\${MAILHUB_CERT_RESTART:-}" >> "$MAILHUB_DEPLOY_TEST_LOG"
- exit "\${MAILHUB_DEPLOY_TEST_SYNC_STATUS:-0}"
- `);
- t.after(() => rmSync(root, { recursive: true, force: true }));
- return { root, fakeBin, remoteDir, logFile };
- }
- function runDeploy(fixture, { syncStatus = '0' } = {}) {
- return spawnSync('bash', [scriptPath], {
- cwd: fixture.root,
- encoding: 'utf8',
- env: {
- ...process.env,
- PATH: `${fixture.fakeBin}${path.delimiter}${process.env.PATH ?? ''}`,
- MAILHUB_DEPLOY_REMOTE: 'deploy@example.test',
- MAILHUB_DEPLOY_DIR: fixture.remoteDir,
- MAILHUB_DEPLOY_BRANCH: 'main',
- MAILHUB_DEPLOY_GIT_URL: 'ssh://git.example.test/mailhub.git',
- MAILHUB_DEPLOY_TEST_LOG: fixture.logFile,
- MAILHUB_DEPLOY_TEST_REMOTE_DIR: fixture.remoteDir,
- MAILHUB_DEPLOY_TEST_SYNC_STATUS: syncStatus
- }
- });
- }
- function writeExecutable(filePath, contents) {
- writeFileSync(filePath, contents);
- chmodSync(filePath, 0o755);
- }
- function readEvents(logFile) {
- return readFileSync(logFile, 'utf8').trim().split('\n').filter(Boolean);
- }
|