mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-20 16:07:11 +08:00
chore(ql3): add opt-in deployment diagnostics
This commit is contained in:
@@ -715,6 +715,7 @@ jobs:
|
|||||||
HEADLESS_IMAGE: qinglong3-local-application:ci-${{ matrix.image_arch }}
|
HEADLESS_IMAGE: qinglong3-local-application:ci-${{ matrix.image_arch }}
|
||||||
CONSOLE_IMAGE: qinglong3-local-console:ci-${{ matrix.image_arch }}
|
CONSOLE_IMAGE: qinglong3-local-console:ci-${{ matrix.image_arch }}
|
||||||
OPERATOR_IMAGE: qinglong3-local-operator:ci-${{ matrix.image_arch }}
|
OPERATOR_IMAGE: qinglong3-local-operator:ci-${{ matrix.image_arch }}
|
||||||
|
QL3_LOCAL_DEPLOYMENT_DIAGNOSTICS: '1'
|
||||||
TRIAL_VARIANT: ${{ inputs.local_alpha_variant }}
|
TRIAL_VARIANT: ${{ inputs.local_alpha_variant }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
consumeLocalServiceManagerCutoverOutcomeCommandFile,
|
consumeLocalServiceManagerCutoverOutcomeCommandFile,
|
||||||
consumeLocalServiceManagerLegacyRollbackCommandFile,
|
consumeLocalServiceManagerLegacyRollbackCommandFile,
|
||||||
inspectLocalDeploymentStatusCommandFile,
|
inspectLocalDeploymentStatusCommandFile,
|
||||||
|
LocalDeploymentConfigurationError,
|
||||||
preflightLocalDeploymentComposeCommandFile,
|
preflightLocalDeploymentComposeCommandFile,
|
||||||
prepareLocalServiceManagerIntentCommandFile,
|
prepareLocalServiceManagerIntentCommandFile,
|
||||||
prepareLocalServiceManagerLegacyRollbackCommandFile,
|
prepareLocalServiceManagerLegacyRollbackCommandFile,
|
||||||
@@ -282,8 +283,15 @@ async function main(argv: readonly string[]): Promise<void> {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
const candidate = error as {
|
const candidate = error as {
|
||||||
readonly code?: unknown;
|
readonly code?: unknown;
|
||||||
|
readonly message?: unknown;
|
||||||
readonly name?: unknown;
|
readonly name?: unknown;
|
||||||
};
|
};
|
||||||
|
const diagnosticMessage =
|
||||||
|
process.env.QL3_LOCAL_DEPLOYMENT_DIAGNOSTICS === '1' &&
|
||||||
|
error instanceof LocalDeploymentConfigurationError &&
|
||||||
|
typeof candidate.message === 'string'
|
||||||
|
? { message: candidate.message }
|
||||||
|
: {};
|
||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`${JSON.stringify({
|
`${JSON.stringify({
|
||||||
code:
|
code:
|
||||||
@@ -291,6 +299,7 @@ async function main(argv: readonly string[]): Promise<void> {
|
|||||||
? candidate.code
|
? candidate.code
|
||||||
: 'QL3_LOCAL_DEPLOYMENT_FAILED',
|
: 'QL3_LOCAL_DEPLOYMENT_FAILED',
|
||||||
name: typeof candidate.name === 'string' ? candidate.name : 'Error',
|
name: typeof candidate.name === 'string' ? candidate.name : 'Error',
|
||||||
|
...diagnosticMessage,
|
||||||
})}\n`,
|
})}\n`,
|
||||||
);
|
);
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
|
|||||||
@@ -1000,6 +1000,42 @@ test('status CLI is private-command-only and emits no deployment authority', asy
|
|||||||
assert.equal(rejected.stderr.includes(state.deploymentRoot), false);
|
assert.equal(rejected.stderr.includes(state.deploymentRoot), false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('deployment CLI exposes configuration detail only under explicit diagnostics', (t) => {
|
||||||
|
const state = fixture(t, 'compose');
|
||||||
|
const commandPath = path.join(state.managementRoot, 'invalid-command.json');
|
||||||
|
fs.writeFileSync(commandPath, '{}\n', { mode: 0o600 });
|
||||||
|
const cli = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../dist/deployment/localDeploymentCli.js',
|
||||||
|
);
|
||||||
|
const normal = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[cli, 'prepare', '--command-file', commandPath],
|
||||||
|
{ encoding: 'utf8' },
|
||||||
|
);
|
||||||
|
assert.equal(normal.status, 1);
|
||||||
|
assert.deepEqual(JSON.parse(normal.stderr), {
|
||||||
|
code: 'QL3_LOCAL_DEPLOYMENT_CONFIGURATION_INVALID',
|
||||||
|
name: 'LocalDeploymentConfigurationError',
|
||||||
|
});
|
||||||
|
|
||||||
|
const diagnostic = spawnSync(
|
||||||
|
process.execPath,
|
||||||
|
[cli, 'prepare', '--command-file', commandPath],
|
||||||
|
{
|
||||||
|
encoding: 'utf8',
|
||||||
|
env: { ...process.env, QL3_LOCAL_DEPLOYMENT_DIAGNOSTICS: '1' },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
assert.equal(diagnostic.status, 1);
|
||||||
|
assert.deepEqual(JSON.parse(diagnostic.stderr), {
|
||||||
|
code: 'QL3_LOCAL_DEPLOYMENT_CONFIGURATION_INVALID',
|
||||||
|
name: 'LocalDeploymentConfigurationError',
|
||||||
|
message:
|
||||||
|
'Local deployment configuration is invalid: command shape is invalid',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
test('durable status keeps live supervisor and database authority out of its module', () => {
|
test('durable status keeps live supervisor and database authority out of its module', () => {
|
||||||
const source = fs.readFileSync(
|
const source = fs.readFileSync(
|
||||||
path.resolve(__dirname, '../src/deployment/localDeploymentStatus.ts'),
|
path.resolve(__dirname, '../src/deployment/localDeploymentStatus.ts'),
|
||||||
|
|||||||
@@ -210,6 +210,8 @@ run_deploy() {
|
|||||||
--mount "type=bind,src=$decision_parent,dst=$decision_parent,readonly"
|
--mount "type=bind,src=$decision_parent,dst=$decision_parent,readonly"
|
||||||
[ -z "$secondary_decision_parent" ] || set -- "$@" \
|
[ -z "$secondary_decision_parent" ] || set -- "$@" \
|
||||||
--mount "type=bind,src=$secondary_decision_parent,dst=$secondary_decision_parent,readonly"
|
--mount "type=bind,src=$secondary_decision_parent,dst=$secondary_decision_parent,readonly"
|
||||||
|
[ "${QL3_LOCAL_DEPLOYMENT_DIAGNOSTICS:-0}" != 1 ] || set -- "$@" \
|
||||||
|
--env QL3_LOCAL_DEPLOYMENT_DIAGNOSTICS=1
|
||||||
set -- "$@" "$OPERATOR_IMAGE" deploy "$subcommand" \
|
set -- "$@" "$OPERATOR_IMAGE" deploy "$subcommand" \
|
||||||
--command-file "$command_root/$command_file"
|
--command-file "$command_root/$command_file"
|
||||||
result_stage="$result_root/.$result_file.$$"
|
result_stage="$result_root/.$result_file.$$"
|
||||||
|
|||||||
Reference in New Issue
Block a user