@zip.js/zip.js 2.8.60 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deno.json +1 -1
- package/dist/zip-core-external.js +39 -22
- package/dist/zip-core-external.min.js +1 -1
- package/dist/zip-core.js +39 -21
- package/dist/zip-core.min.js +1 -1
- package/dist/zip-fs-core-external.js +45 -30
- package/dist/zip-fs-core-external.min.js +1 -1
- package/dist/zip-fs-core.js +45 -29
- package/dist/zip-fs-core.min.js +1 -1
- package/dist/zip-fs-external.js +45 -30
- package/dist/zip-fs-external.min.js +1 -1
- package/dist/zip-fs-native.js +45 -29
- package/dist/zip-fs-native.min.js +1 -1
- package/dist/zip-fs.js +45 -29
- package/dist/zip-fs.min.js +1 -1
- package/dist/zip-legacy.js +39 -21
- package/dist/zip-legacy.min.js +1 -1
- package/dist/zip-native.js +39 -21
- package/dist/zip-native.min.js +1 -1
- package/dist/zip.js +39 -21
- package/dist/zip.min.js +1 -1
- package/index-native.cjs +45 -29
- package/index-native.min.js +1 -1
- package/index.cjs +45 -29
- package/index.d.cts +17 -2
- package/index.d.ts +17 -2
- package/index.min.js +1 -1
- package/lib/core/streams/codecs/crc32.js +1 -1
- package/lib/core/util/decode-cp437.js +1 -1
- package/lib/core/version.js +1 -1
- package/lib/core/zip-fs.js +5 -4
- package/lib/core/zip-reader.js +7 -0
- package/lib/core/zip-writer.js +37 -31
- package/lib/zip-core-reader.js +1 -0
- package/package.json +2 -1
- package/release.sh +47 -0
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
// Every table MUST stay a PACKED_SMI array: build with array literals (not `new Array(n)`,
|
|
34
34
|
// which is HOLEY) and store the signed int32 XOR result (no `>>> 0`). An unsigned or holey
|
|
35
35
|
// table becomes a V8 FixedDoubleArray whose every hot-loop lookup unboxes a double (~1.6x
|
|
36
|
-
// slower). Signedness is irrelevant to the result
|
|
36
|
+
// slower). Signedness is irrelevant to the result: the reads mask/shift it and the final
|
|
37
37
|
// `~crc` normalizes it. Do NOT reintroduce `>>> 0` here or switch to `new Array(256)`.
|
|
38
38
|
const T = [[], [], [], [], [], [], [], []];
|
|
39
39
|
for (let n = 0; n < 256; n++) {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
/* global TextDecoder */
|
|
30
30
|
|
|
31
|
-
const CP437 = "\0
|
|
31
|
+
const CP437 = "\0\u263A\u263B\u2665\u2666\u2663\u2660\u2022\u25D8\u25CB\u25D9\u2642\u2640\u266A\u266B\u263C\u25BA\u25C4\u2195\u203C\u00B6\u00A7\u25AC\u21A8\u2191\u2193\u2192\u2190\u221F\u2194\u25B2\u25BC !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u2302\u00C7\u00FC\u00E9\u00E2\u00E4\u00E0\u00E5\u00E7\u00EA\u00EB\u00E8\u00EF\u00EE\u00EC\u00C4\u00C5\u00C9\u00E6\u00C6\u00F4\u00F6\u00F2\u00FB\u00F9\u00FF\u00D6\u00DC\u00A2\u00A3\u00A5\u20A7\u0192\u00E1\u00ED\u00F3\u00FA\u00F1\u00D1\u00AA\u00BA\u00BF\u2310\u00AC\u00BD\u00BC\u00A1\u00AB\u00BB\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255D\u255C\u255B\u2510\u2514\u2534\u252C\u251C\u2500\u253C\u255E\u255F\u255A\u2554\u2569\u2566\u2560\u2550\u256C\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256B\u256A\u2518\u250C\u2588\u2584\u258C\u2590\u2580\u03B1\u00DF\u0393\u03C0\u03A3\u03C3\u00B5\u03C4\u03A6\u0398\u03A9\u03B4\u221E\u03C6\u03B5\u2229\u2261\u00B1\u2265\u2264\u2320\u2321\u00F7\u2248\u00B0\u2219\u00B7\u221A\u207F\u00B2\u25A0\u00A0".split("");
|
|
32
32
|
const VALID_CP437 = CP437.length == 256;
|
|
33
33
|
|
|
34
34
|
export {
|
package/lib/core/version.js
CHANGED
package/lib/core/zip-fs.js
CHANGED
|
@@ -540,12 +540,13 @@ class ZipDirectoryEntry extends ZipEntry {
|
|
|
540
540
|
if (options.bufferedWrite === UNDEFINED_VALUE) {
|
|
541
541
|
options.bufferedWrite = true;
|
|
542
542
|
}
|
|
543
|
-
const
|
|
544
|
-
(options.keepOrder !== false && zipEntry.children.every(child => !child.children.length));
|
|
545
|
-
return getEntriesSize(options, zipEntry.getChildren({ recursive: true }).filter(child => !isImplicitDirectory(child)).map(child => {
|
|
543
|
+
const entries = zipEntry.getChildren({ recursive: true }).filter(child => !isImplicitDirectory(child)).map(child => {
|
|
546
544
|
const { name, entryOptions } = getChildEntryOptions(child, zipEntry, options);
|
|
547
545
|
return { name, size: child.directory ? 0 : getDeterminedSize(child, isPassThrough(child, options)), options: entryOptions };
|
|
548
|
-
})
|
|
546
|
+
});
|
|
547
|
+
const writeOrderGuaranteed = !options.bufferedWrite ||
|
|
548
|
+
(entries.every(entry => entry.options.keepOrder !== false) && zipEntry.children.every(child => !child.children.length));
|
|
549
|
+
return getEntriesSize(options, entries, writeOrderGuaranteed, options.globalComment);
|
|
549
550
|
}
|
|
550
551
|
|
|
551
552
|
getChildByName(name) {
|
package/lib/core/zip-reader.js
CHANGED
|
@@ -205,6 +205,7 @@ const WARNING_UNKNOWN_ZIP64_EXTENSIBLE_DATA = "unknown zip64 extensible data";
|
|
|
205
205
|
const WARNING_WRAPPED_ENTRIES_COUNT = "wrapped entries count";
|
|
206
206
|
const WARNING_APPENDED_DATA = "appended data";
|
|
207
207
|
const WARNING_PREPENDED_DATA = "prepended data";
|
|
208
|
+
const WARNING_PREPENDED_CENTRAL_DIRECTORY = "prepended central directory";
|
|
208
209
|
const WARNING_TRAILING_CENTRAL_DIRECTORY_DATA = "trailing central directory data";
|
|
209
210
|
const WARNING_DUPLICATE_FILENAME = "duplicate filename";
|
|
210
211
|
const WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY = "mismatched zip64 end of central directory record";
|
|
@@ -298,6 +299,7 @@ class ZipReader {
|
|
|
298
299
|
let diskNumber = getUint16(endOfDirectoryView, 6);
|
|
299
300
|
let filesLength = getUint16(endOfDirectoryView, 10);
|
|
300
301
|
let prependedDataLength = 0;
|
|
302
|
+
let prependedCentralDirectory;
|
|
301
303
|
let startOffset;
|
|
302
304
|
let zip64EndOfDirectory;
|
|
303
305
|
let zip64EndOfDirectoryVersion2;
|
|
@@ -401,6 +403,7 @@ class ZipReader {
|
|
|
401
403
|
directoryDataOffset = expectedDirectoryDataOffset;
|
|
402
404
|
if (directoryDataOffset > originalDirectoryDataOffset) {
|
|
403
405
|
prependedDataLength += directoryDataOffset - originalDirectoryDataOffset;
|
|
406
|
+
prependedCentralDirectory = storedPointsAtDirectory;
|
|
404
407
|
}
|
|
405
408
|
directoryArray = await readUint8Array(reader, directoryDataOffset, directoryDataLength);
|
|
406
409
|
directoryView = getDataView(directoryArray);
|
|
@@ -628,6 +631,9 @@ class ZipReader {
|
|
|
628
631
|
if (prependedDataLength || (filesLength && startOffset > SPLIT_ZIP_FILE_SIGNATURE_LENGTH)) {
|
|
629
632
|
addWarning(warnings, WARNING_PREPENDED_DATA);
|
|
630
633
|
}
|
|
634
|
+
if (prependedCentralDirectory) {
|
|
635
|
+
addWarning(warnings, WARNING_PREPENDED_CENTRAL_DIRECTORY);
|
|
636
|
+
}
|
|
631
637
|
if (extractPrependedData) {
|
|
632
638
|
zipReader.prependedData = startOffset > splitZipSignatureLength ?
|
|
633
639
|
await readUint8Array(reader, splitZipSignatureLength, startOffset - splitZipSignatureLength) :
|
|
@@ -756,6 +762,7 @@ export {
|
|
|
756
762
|
WARNING_WRAPPED_ENTRIES_COUNT,
|
|
757
763
|
WARNING_APPENDED_DATA,
|
|
758
764
|
WARNING_PREPENDED_DATA,
|
|
765
|
+
WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
759
766
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
760
767
|
WARNING_DUPLICATE_FILENAME,
|
|
761
768
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
package/lib/core/zip-writer.js
CHANGED
|
@@ -56,17 +56,16 @@
|
|
|
56
56
|
* the insertion order of the `fileEntries` map. addFile() reserves each entry's slot synchronously in
|
|
57
57
|
* add() call order, before initializing the reader, so concurrent entries whose readers
|
|
58
58
|
* initialize at different speeds are still listed in call order.
|
|
59
|
-
* - `fileEntry.lockFileEntry` chains every entry to the previous one
|
|
60
|
-
*
|
|
61
|
-
* the
|
|
62
|
-
*
|
|
59
|
+
* - `fileEntry.lockFileEntry` chains every entry to the previous one; awaiting it serializes the
|
|
60
|
+
* physical writes when `keepOrder` is set. addFile() claims the link in the same synchronous
|
|
61
|
+
* prologue as the central directory slot, so the physical layout follows the add() call order
|
|
62
|
+
* as well, whatever the readers do. The lock is released for every entry, including the ones
|
|
63
|
+
* failing before they reach getFileEntry().
|
|
63
64
|
* - `zipWriter.lockWriter`/`writerLocked` is the mutex over the writer; only the holder may write
|
|
64
65
|
* into it or read the position variables above.
|
|
65
|
-
* -
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* before awaiting the lock of the previous entry, while a buffered predecessor needs the
|
|
69
|
-
* writer lock to be flushed.
|
|
66
|
+
* - Both write paths await the lock of the previous entry before requesting the writer lock.
|
|
67
|
+
* Requesting it first would deadlock an entry written directly into the writer (i.e. without
|
|
68
|
+
* being buffered) against a buffered predecessor, which needs that same lock to be flushed.
|
|
70
69
|
* - `lastFileEntry` is the tail of the lock chain (the most recently added entry).
|
|
71
70
|
*
|
|
72
71
|
* Failures:
|
|
@@ -689,6 +688,13 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
689
688
|
const { comment } = metadataInfo;
|
|
690
689
|
const extraField = options[PROPERTY_NAME_EXTRA_FIELD];
|
|
691
690
|
zipWriter.fileEntries.set(name, UNDEFINED_VALUE);
|
|
691
|
+
const previousFileEntry = zipWriter.lastFileEntry;
|
|
692
|
+
const pendingFileEntry = {};
|
|
693
|
+
let releaseLockFileEntry;
|
|
694
|
+
if (metadataInfo.resolvedOptions.keepOrder) {
|
|
695
|
+
pendingFileEntry.lockFileEntry = new Promise(resolve => releaseLockFileEntry = resolve);
|
|
696
|
+
}
|
|
697
|
+
zipWriter.lastFileEntry = pendingFileEntry;
|
|
692
698
|
let fileEntry;
|
|
693
699
|
try {
|
|
694
700
|
const { resolvedOptions } = metadataInfo;
|
|
@@ -710,10 +716,21 @@ async function addFile(zipWriter, name, reader, options) {
|
|
|
710
716
|
const headerInfo = getHeaderInfo(options);
|
|
711
717
|
const dataDescriptorInfo = getDataDescriptorInfo(options);
|
|
712
718
|
const metadataSize = getLength(headerInfo.localHeaderArray, dataDescriptorInfo.dataDescriptorArray);
|
|
713
|
-
fileEntry = await getFileEntry(zipWriter, name, reader, {
|
|
719
|
+
fileEntry = await getFileEntry(zipWriter, name, reader, {
|
|
720
|
+
headerInfo,
|
|
721
|
+
dataDescriptorInfo,
|
|
722
|
+
metadataSize,
|
|
723
|
+
fileEntry: pendingFileEntry,
|
|
724
|
+
previousFileEntry,
|
|
725
|
+
releaseLockFileEntry
|
|
726
|
+
}, options);
|
|
714
727
|
} catch (error) {
|
|
715
728
|
zipWriter.fileEntries.delete(name);
|
|
716
729
|
throw error;
|
|
730
|
+
} finally {
|
|
731
|
+
if (releaseLockFileEntry) {
|
|
732
|
+
releaseLockFileEntry(previousFileEntry && previousFileEntry.lockFileEntry);
|
|
733
|
+
}
|
|
717
734
|
}
|
|
718
735
|
Object.assign(fileEntry, {
|
|
719
736
|
name,
|
|
@@ -1101,7 +1118,6 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1101
1118
|
}
|
|
1102
1119
|
const usdz = writerOptions[OPTION_USDZ];
|
|
1103
1120
|
const files = new Map();
|
|
1104
|
-
let layoutDependsOnWriteOrder = Boolean(usdz);
|
|
1105
1121
|
const initialOffset = writerOptions[OPTION_OFFSET] === UNDEFINED_VALUE ? 0 : writerOptions[OPTION_OFFSET];
|
|
1106
1122
|
let offset = initialOffset;
|
|
1107
1123
|
let minimumEntrySize = INFINITY_VALUE;
|
|
@@ -1147,9 +1163,7 @@ async function getEntriesSize(writerOptions, entries, writeOrderGuaranteed, comm
|
|
|
1147
1163
|
minimumEntrySize = Math.min(minimumEntrySize, entrySize);
|
|
1148
1164
|
offset += entrySize;
|
|
1149
1165
|
}
|
|
1150
|
-
|
|
1151
|
-
layoutDependsOnWriteOrder = true;
|
|
1152
|
-
}
|
|
1166
|
+
const layoutDependsOnWriteOrder = files.size > 1 && (usdz || offset - minimumEntrySize >= MAX_32_BITS);
|
|
1153
1167
|
if (layoutDependsOnWriteOrder && !writeOrderGuaranteed) {
|
|
1154
1168
|
throw new Error(ERR_UNDETERMINED_SIZE);
|
|
1155
1169
|
}
|
|
@@ -1177,27 +1191,23 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1177
1191
|
signal
|
|
1178
1192
|
} = options;
|
|
1179
1193
|
const {
|
|
1180
|
-
headerInfo
|
|
1194
|
+
headerInfo,
|
|
1195
|
+
fileEntry: pendingFileEntry,
|
|
1196
|
+
previousFileEntry,
|
|
1197
|
+
releaseLockFileEntry
|
|
1181
1198
|
} = entryInfo;
|
|
1182
1199
|
const usdz = zipWriter.options[OPTION_USDZ];
|
|
1183
|
-
|
|
1184
|
-
let fileEntry = {};
|
|
1200
|
+
let fileEntry = pendingFileEntry;
|
|
1185
1201
|
let bufferedWrite;
|
|
1186
1202
|
let releaseLockWriter;
|
|
1187
|
-
let releaseLockCurrentFileEntry;
|
|
1188
1203
|
let writingBufferedEntryData;
|
|
1189
1204
|
let writingEntryData;
|
|
1190
1205
|
let writerSizeBeforeEntry;
|
|
1191
1206
|
let flushedBufferedSize = 0;
|
|
1192
1207
|
let fileWriter;
|
|
1208
|
+
const lockPreviousFileEntry = keepOrder && previousFileEntry ? previousFileEntry.lockFileEntry : UNDEFINED_VALUE;
|
|
1193
1209
|
fileEntries.set(name, fileEntry);
|
|
1194
|
-
zipWriter.lastFileEntry = fileEntry;
|
|
1195
1210
|
try {
|
|
1196
|
-
let lockPreviousFileEntry;
|
|
1197
|
-
if (keepOrder) {
|
|
1198
|
-
lockPreviousFileEntry = previousFileEntry && previousFileEntry.lockFileEntry;
|
|
1199
|
-
requestLockCurrentFileEntry();
|
|
1200
|
-
}
|
|
1201
1211
|
if (options.bufferedWrite || !keepOrder || zipWriter.writerLocked || zipWriter.bufferedWrites || (!dataDescriptor && !emptyEntry)) {
|
|
1202
1212
|
bufferedWrite = true;
|
|
1203
1213
|
zipWriter.bufferedWrites++;
|
|
@@ -1210,6 +1220,7 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1210
1220
|
await initStream(writer);
|
|
1211
1221
|
} else {
|
|
1212
1222
|
fileWriter = writer;
|
|
1223
|
+
await lockPreviousFileEntry;
|
|
1213
1224
|
await requestLockWriter();
|
|
1214
1225
|
}
|
|
1215
1226
|
await initStream(fileWriter);
|
|
@@ -1222,7 +1233,6 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1222
1233
|
}
|
|
1223
1234
|
const { localHeaderArray } = headerInfo;
|
|
1224
1235
|
if (!bufferedWrite) {
|
|
1225
|
-
await lockPreviousFileEntry;
|
|
1226
1236
|
await skipDiskIfNeeded();
|
|
1227
1237
|
}
|
|
1228
1238
|
const diskNumberStart = getDiskNumber(writer);
|
|
@@ -1287,8 +1297,8 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1287
1297
|
if (bufferedWrite) {
|
|
1288
1298
|
zipWriter.bufferedWrites--;
|
|
1289
1299
|
}
|
|
1290
|
-
if (
|
|
1291
|
-
|
|
1300
|
+
if (releaseLockFileEntry) {
|
|
1301
|
+
releaseLockFileEntry(lockPreviousFileEntry);
|
|
1292
1302
|
}
|
|
1293
1303
|
if (releaseLockWriter) {
|
|
1294
1304
|
releaseLockWriter();
|
|
@@ -1302,10 +1312,6 @@ async function getFileEntry(zipWriter, name, reader, entryInfo, options) {
|
|
|
1302
1312
|
}
|
|
1303
1313
|
}
|
|
1304
1314
|
|
|
1305
|
-
function requestLockCurrentFileEntry() {
|
|
1306
|
-
fileEntry.lockFileEntry = new Promise(resolve => releaseLockCurrentFileEntry = resolve);
|
|
1307
|
-
}
|
|
1308
|
-
|
|
1309
1315
|
async function requestLockWriter() {
|
|
1310
1316
|
zipWriter.writerLocked = true;
|
|
1311
1317
|
const { lockWriter } = zipWriter;
|
package/lib/zip-core-reader.js
CHANGED
|
@@ -66,6 +66,7 @@ export {
|
|
|
66
66
|
WARNING_WRAPPED_ENTRIES_COUNT,
|
|
67
67
|
WARNING_APPENDED_DATA,
|
|
68
68
|
WARNING_PREPENDED_DATA,
|
|
69
|
+
WARNING_PREPENDED_CENTRAL_DIRECTORY,
|
|
69
70
|
WARNING_TRAILING_CENTRAL_DIRECTORY_DATA,
|
|
70
71
|
WARNING_DUPLICATE_FILENAME,
|
|
71
72
|
WARNING_MISMATCHED_ZIP64_END_OF_CENTRAL_DIRECTORY,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "A JavaScript library to zip and unzip files in the browser, Deno and Node.js",
|
|
4
4
|
"author": "Gildas Lormeau",
|
|
5
5
|
"license": "BSD-3-Clause",
|
|
6
|
-
"version": "2.
|
|
6
|
+
"version": "2.9.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"keywords": [
|
|
9
9
|
"zip",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"bump-minor": "npm version minor --no-git-tag-version && npm run bump-commit",
|
|
40
40
|
"bump-major": "npm version major --no-git-tag-version && npm run bump-commit",
|
|
41
41
|
"bump-commit": "npm run build && git commit -m \"bump up version\" package.json package-lock.json deno.json lib/core/version.js dist index.cjs index-native.cjs index.min.js index-native.min.js lib/core/web-worker-inline-wasm.js lib/core/web-worker-inline-native.js",
|
|
42
|
+
"release": "sh ./release.sh",
|
|
42
43
|
"lint": "npx eslint . && deno lint",
|
|
43
44
|
"test": "npm run test-node && npm run test-deno && npm run test-bun && npm run test-node-dist && npm run test-deno-dist && npm run test-bun-dist && npm run test-web-streams-polyfill && npm run test-types && npm run test-api-symmetry && npm run test-api-shape && npm run test-api-mangling",
|
|
44
45
|
"test-browsers": "npm run test-chrome && npm run test-firefox && npm run test-safari",
|
package/release.sh
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Creates the GitHub release for the version declared in package.json, which triggers the publish
|
|
3
|
+
# workflow. It only encodes the checks a release must pass anyway: the released commit is the pushed
|
|
4
|
+
# master head, its tests concluded green (the publish gate would otherwise fail after the release
|
|
5
|
+
# exists, and recovering means deleting the release and the tag), and the tag targets the branch
|
|
6
|
+
# because the API rejects abbreviated commit SHAs as a target.
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
notes_file=$1
|
|
10
|
+
if [ -z "$notes_file" ]; then
|
|
11
|
+
echo "usage: npm run release -- <notes-file>" >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
if [ ! -f "$notes_file" ]; then
|
|
15
|
+
echo "notes file not found: $notes_file" >&2
|
|
16
|
+
exit 1
|
|
17
|
+
fi
|
|
18
|
+
version=$(node -p "require('./package.json').version")
|
|
19
|
+
tag="v$version"
|
|
20
|
+
if gh release view "$tag" >/dev/null 2>&1; then
|
|
21
|
+
echo "release $tag already exists" >&2
|
|
22
|
+
exit 1
|
|
23
|
+
fi
|
|
24
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
25
|
+
echo "the working tree is not clean" >&2
|
|
26
|
+
exit 1
|
|
27
|
+
fi
|
|
28
|
+
git fetch origin master
|
|
29
|
+
sha=$(git rev-parse HEAD)
|
|
30
|
+
if [ "$sha" != "$(git rev-parse origin/master)" ]; then
|
|
31
|
+
echo "HEAD is not origin/master, push the bump commit first" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
fi
|
|
34
|
+
run=$(gh api "repos/{owner}/{repo}/actions/workflows/test.yml/runs?head_sha=$sha&per_page=1" \
|
|
35
|
+
--jq 'if (.workflow_runs | length) == 0 then "none none none" else (.workflow_runs[0] | "\(.status) \(.conclusion) \(.html_url)") end')
|
|
36
|
+
run_status=$(echo "$run" | cut -d " " -f 1)
|
|
37
|
+
conclusion=$(echo "$run" | cut -d " " -f 2)
|
|
38
|
+
url=$(echo "$run" | cut -d " " -f 3)
|
|
39
|
+
if [ "$run_status" = "none" ]; then
|
|
40
|
+
echo "no test run found for $sha yet, wait for it and run this again" >&2
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
if [ "$run_status" != "completed" ] || [ "$conclusion" != "success" ]; then
|
|
44
|
+
echo "the tests of $sha concluded $run_status/$conclusion, only a green commit can be released: $url" >&2
|
|
45
|
+
exit 1
|
|
46
|
+
fi
|
|
47
|
+
gh release create "$tag" --target master --notes-file "$notes_file"
|