Feature/gitops #37

Merged
niko merged 23 commits from feature/gitops into main 2026-06-22 10:37:15 +03:00
3 changed files with 51 additions and 40 deletions
Showing only changes of commit 1385afcca6 - Show all commits
@@ -1,11 +1,12 @@
const { execSync } = require('child_process'); const { spawnSync, execSync } = require('child_process');
const { Before, When, Then } = require('@cucumber/cucumber'); const { Before, After, Given, When, Then } = require('@cucumber/cucumber');
const path = require('path'); const path = require('path');
const PROJECT_ROOT = path.resolve(__dirname, '..', '..', '..'); const PROJECT_ROOT = path.resolve(__dirname, '..', '..', '..');
const MOCK_SCRIPT = path.join(PROJECT_ROOT, 'tests', 'helpers', 'mock-api.sh'); const MOCK_SCRIPT = path.join(PROJECT_ROOT, 'tests', 'helpers', 'mock-api.sh');
const GITOPS_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'gitops-update.sh'); const GITOPS_SCRIPT = path.join(PROJECT_ROOT, 'scripts', 'gitops-update.sh');
const MOCK_HELPERS = path.join(PROJECT_ROOT, 'tests', 'helpers'); const MOCK_HELPERS = path.join(PROJECT_ROOT, 'tests', 'helpers');
const REQ_FILE = '/tmp/gitops-mock-requests.log';
const BASE_ENV = { const BASE_ENV = {
INPUT_FILE: 'dev/Chart.yaml', INPUT_FILE: 'dev/Chart.yaml',
@@ -20,58 +21,75 @@ const BASE_ENV = {
Before({ tags: '@mock' }, function () { Before({ tags: '@mock' }, function () {
process.env.PATH = `${MOCK_HELPERS}:${process.env.PATH}`; process.env.PATH = `${MOCK_HELPERS}:${process.env.PATH}`;
try { execSync('rm -f /tmp/gitops-mock-requests.log', { stdio: 'ignore' }); } catch (_) {}
// Restart mock with known request file path
const result = spawnSync('bash', ['-c', `
source "${MOCK_SCRIPT}"
mock_stop 2>/dev/null
MOCK_REQUEST_FILE="${REQ_FILE}"
mock_start
sleep 0.5
curl -s -o /dev/null -w "%{http_code}" --max-time 3 http://localhost:18080/api/v1/repos/health
`], {
cwd: PROJECT_ROOT, encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe']
});
const code = result.stdout.trim();
if (!code.startsWith('2') && !code.startsWith('4')) {
throw new Error(`GitOps mock restart failed: ${result.stderr.substring(0,200)}`);
}
});
After({ tags: '@mock' }, function () {
spawnSync('bash', ['-c', `source "${MOCK_SCRIPT}" && mock_stop 2>/dev/null`], { stdio: 'ignore' });
try { execSync('rm -f /tmp/gitops-mock-requests.log', { stdio: 'ignore' }); } catch (_) {}
}); });
function bash(cmd) { function bash(cmd) {
try { const result = spawnSync('bash', ['-c', cmd], {
const out = execSync(`bash -c '${cmd}'`, { cwd: PROJECT_ROOT,
cwd: PROJECT_ROOT, encoding: 'utf-8',
encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'],
stdio: ['pipe', 'pipe', 'pipe'], });
}); return { status: result.status, stdout: result.stdout || '', stderr: result.stderr || '' };
return { status: 0, stdout: out, stderr: '' };
} catch (e) {
return { status: e.status, stdout: e.stdout || '', stderr: e.stderr || '' };
}
} }
function getFirstBody() { function getFirstBody() {
return bash(`source "${MOCK_SCRIPT}" && _get_request_file && mock_get_first_request_body`).stdout.trim(); return bash(`grep -A1 '^POST ' "${REQ_FILE}" 2>/dev/null | head -2 | tail -1 || echo ""`).stdout.trim();
} }
function getFirstPath() { function getFirstPath() {
return bash(`source "${MOCK_SCRIPT}" && _get_request_file && mock_get_first_request_path`).stdout.trim(); return bash(`grep '^POST ' "${REQ_FILE}" 2>/dev/null | head -1 | awk '{print $2}' || echo ""`).stdout.trim();
} }
function getLastBody() { function getLastBody() {
return bash(`source "${MOCK_SCRIPT}" && _get_request_file && mock_get_request_body`).stdout.trim(); return bash(`grep -A1 '^POST ' "${REQ_FILE}" 2>/dev/null | grep -v '^POST ' | tail -1 || echo ""`).stdout.trim();
} }
function getLastPath() { function getLastPath() {
return bash(`source "${MOCK_SCRIPT}" && _get_request_file && mock_get_request_path`).stdout.trim(); return bash(`grep '^POST ' "${REQ_FILE}" 2>/dev/null | tail -1 | awk '{print $2}' || echo ""`).stdout.trim();
} }
function requestCount() { function requestCount() {
const rf = bash(`source "${MOCK_SCRIPT}" && _get_request_file`).stdout.trim(); return parseInt(bash(`grep -c '^POST ' "${REQ_FILE}" 2>/dev/null || echo 0`).stdout.trim(), 10) || 0;
const count = bash(`grep -c '^POST ' "${rf}" 2>/dev/null || echo 0`).stdout.trim();
return parseInt(count, 10) || 0;
} }
function runScript(envOverrides) { function runScript(envOverrides) {
const env = { ...BASE_ENV, ...envOverrides }; const env = { ...BASE_ENV, ...envOverrides };
const envStr = Object.entries(env) const scriptPath = `/tmp/gitops-run-${Date.now()}.sh`;
.map(([k, v]) => { const exports = Object.entries(env)
const escaped = v.replace(/'/g, "'\\''"); .map(([k, v]) => `export ${k}="${v.replace(/"/g, '\\"')}"`)
return `${k}='${escaped}'`; .join('\n');
}) require('fs').writeFileSync(scriptPath, `${exports}\nexport PATH="${MOCK_HELPERS}:$PATH"\nset -euo pipefail\nbash "${GITOPS_SCRIPT}"\nsync\n`, 'utf8');
.join(' '); try {
return bash(`${envStr} bash "${GITOPS_SCRIPT}"`); return bash(`bash "${scriptPath}"`);
} finally {
require('fs').unlinkSync(scriptPath);
}
} }
Given('insufficient environment variables are provided for the GitOps update', function () { Given('insufficient environment variables are provided for the GitOps update', function () {
this.missingVar = 'INPUT_FILE'; this.missingVar = 'INPUT_FILE';
this.envOverrides = {}; this.envOverrides = { INPUT_FILE: '' };
this.envOverrides.INPUT_FILE = '';
}); });
Given('the GitOps repository clone will fail', function () { Given('the GitOps repository clone will fail', function () {
@@ -110,11 +128,11 @@ Then('the caller commit shows a failure status', function () {
}); });
Then('the script exits with error', function () { Then('the script exits with error', function () {
if (this.result.status === 0) throw new Error(`Expected non-zero exit, got 0. stderr: ${this.result.stderr}`); if (this.result.status === 0) throw new Error(`Expected non-zero exit, got 0. stderr: ${this.result.stderr.substring(0,200)}`);
}); });
Then('the script exits successfully', function () { Then('the script exits successfully', function () {
if (this.result.status !== 0) throw new Error(`Expected exit 0, got ${this.result.status}: ${this.result.stderr}`); if (this.result.status !== 0) throw new Error(`Expected exit 0, got ${this.result.status}: ${this.result.stderr.substring(0,200)}`);
}); });
Then('the caller commit shows a success status with a link to the GitOps commit', function () { Then('the caller commit shows a success status with a link to the GitOps commit', function () {
+2 -9
View File
@@ -11,15 +11,8 @@ fi
case "$1" in case "$1" in
clone) clone)
TARGET_DIR="${@: -1}" TARGET_DIR="${@: -1}"
mkdir -p "$TARGET_DIR" mkdir -p "${TARGET_DIR}/$(dirname "$INPUT_FILE")"
cd "$TARGET_DIR" echo 'version: 0.1.0' > "${TARGET_DIR}/${INPUT_FILE}"
git init --initial-branch=main 2>/dev/null
git config user.email "mock@test.com"
git config user.name "Mock Test"
mkdir -p "$(dirname "$INPUT_FILE")"
echo 'version: 0.1.0' > "$INPUT_FILE"
git add -A 2>/dev/null
git commit -m "initial" 2>/dev/null
echo "Cloning into '$TARGET_DIR'..." echo "Cloning into '$TARGET_DIR'..."
;; ;;
add|commit|push|config|init) add|commit|push|config|init)
+1 -1
View File
@@ -46,7 +46,7 @@ mock_clear_sequence() {
mock_start() { mock_start() {
MOCK_RESPONSE_CODE="${MOCK_RESPONSE_CODE:-201}" MOCK_RESPONSE_CODE="${MOCK_RESPONSE_CODE:-201}"
MOCK_REQUEST_FILE=$(mktemp) MOCK_REQUEST_FILE="${MOCK_REQUEST_FILE:-$(mktemp)}"
echo "$MOCK_REQUEST_FILE" > "$MOCK_STATE_FILE" echo "$MOCK_REQUEST_FILE" > "$MOCK_STATE_FILE"
MOCK_CONFIG_FILE=$(mktemp) MOCK_CONFIG_FILE=$(mktemp)