Merge pull request 'KAN-58: Handle empty S3 bucket versioning response' (#156) from fix/KAN-58-empty-s3-versioning into main
macOS checks / Native Rust tests and unsigned build (push) Successful in 1m17s
CI/CD / preconditions (push) Successful in 1s
Native JavaScript checks / Native launcher and release tests (push) Successful in 54s
CI/CD / test_and_check_app (push) Successful in 6m26s
CI/CD / Publish immutable image (push) Successful in 1m23s
macOS release to Hetzner / Validate release ref and configuration (push) Successful in 20s
macOS release to Hetzner / Sign, notarize, verify and publish macOS (push) Failing after 3m24s
macOS checks / Native Rust tests and unsigned build (push) Successful in 1m17s
CI/CD / preconditions (push) Successful in 1s
Native JavaScript checks / Native launcher and release tests (push) Successful in 54s
CI/CD / test_and_check_app (push) Successful in 6m26s
CI/CD / Publish immutable image (push) Successful in 1m23s
macOS release to Hetzner / Validate release ref and configuration (push) Successful in 20s
macOS release to Hetzner / Sign, notarize, verify and publish macOS (push) Failing after 3m24s
Reviewed-on: #156
This commit was merged in pull request #156.
This commit is contained in:
@@ -94,7 +94,26 @@ export async function publishMacos({
|
|||||||
...args,
|
...args,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
const versioning = JSON.parse(s3('get-bucket-versioning', []));
|
const versioningOutput = s3('get-bucket-versioning', [
|
||||||
|
'--output',
|
||||||
|
'json',
|
||||||
|
]).trim();
|
||||||
|
let versioning;
|
||||||
|
try {
|
||||||
|
// AWS CLI prints nothing for a successful empty VersioningConfiguration.
|
||||||
|
versioning = JSON.parse(versioningOutput || '{}');
|
||||||
|
} catch {
|
||||||
|
throw new Error('Invalid JSON from S3 bucket versioning check.');
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!versioning ||
|
||||||
|
typeof versioning !== 'object' ||
|
||||||
|
Array.isArray(versioning)
|
||||||
|
) {
|
||||||
|
throw new Error(
|
||||||
|
'Invalid S3 bucket versioning response: expected an object.',
|
||||||
|
);
|
||||||
|
}
|
||||||
if (versioning.Status) {
|
if (versioning.Status) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Use an unversioned release bucket: Hetzner does not support conditional writes on versioned buckets.',
|
'Use an unversioned release bucket: Hetzner does not support conditional writes on versioned buckets.',
|
||||||
|
|||||||
@@ -38,7 +38,8 @@ function fixture(t) {
|
|||||||
const key = value('--key');
|
const key = value('--key');
|
||||||
events.push({ operation, key });
|
events.push({ operation, key });
|
||||||
if (operation === 'get-bucket-versioning') {
|
if (operation === 'get-bucket-versioning') {
|
||||||
return '{}';
|
assert.equal(value('--output'), 'json');
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
if (operation === 'put-object') {
|
if (operation === 'put-object') {
|
||||||
assert.equal(value('--if-none-match'), '*');
|
assert.equal(value('--if-none-match'), '*');
|
||||||
@@ -103,6 +104,33 @@ test('uploads immutable files and writes completion record after public verifica
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
for (const response of ['', ' \n\t', '{}']) {
|
||||||
|
test(`unversioned bucket response ${JSON.stringify(response)} permits a verified upload`, async (t) => {
|
||||||
|
const f = fixture(t);
|
||||||
|
const run = f.run;
|
||||||
|
f.run = (command, args) => {
|
||||||
|
const result = run(command, args);
|
||||||
|
return args.includes('get-bucket-versioning') ? response : result;
|
||||||
|
};
|
||||||
|
await publishMacos(f);
|
||||||
|
assert.equal(f.objects.size, 3);
|
||||||
|
assert.equal(f.events.at(-1).operation, 'public-get');
|
||||||
|
assert(f.events.at(-1).key.endsWith('/release.json'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const response of ['{', 'null', '[]', '"Enabled"', 'false']) {
|
||||||
|
test(`invalid versioning response ${response} aborts before any upload`, async (t) => {
|
||||||
|
const f = fixture(t);
|
||||||
|
f.run = (_command, args) => {
|
||||||
|
assert(args.includes('get-bucket-versioning'));
|
||||||
|
return response;
|
||||||
|
};
|
||||||
|
await assert.rejects(publishMacos(f), /Invalid .*versioning/);
|
||||||
|
assert.equal(f.objects.size, 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
test('retry accepts byte-identical objects without replacing them', async (t) => {
|
test('retry accepts byte-identical objects without replacing them', async (t) => {
|
||||||
const f = fixture(t);
|
const f = fixture(t);
|
||||||
await publishMacos(f);
|
await publishMacos(f);
|
||||||
|
|||||||
Reference in New Issue
Block a user