@@ -35,7 +35,8 @@ const github = __importStar(__nccwpck_require__(5438));
3535const exec_1 = __nccwpck_require__(1514);
3636const sqlite3_1 = __importDefault(__nccwpck_require__(4946));
3737const sqlite_1 = __nccwpck_require__(2515);
38- const dbfile = 'github-archive.db';
38+ const nanoid_1 = __nccwpck_require__(9140);
39+ const dbfile = 'github-archive.sqlite';
3940const events = [
4041 'issues',
4142 'issue_comment',
@@ -44,6 +45,8 @@ const events = [
4445 'pull_request_review_comment',
4546];
4647async function run() {
48+ const now = new Date().toISOString();
49+ const id = nanoid_1.nanoid();
4750 core.info('[INFO] Usage https://github.com/githubocto/github-archive-action#readme');
4851 core.startGroup('Setup');
4952 // Configure git user/email
@@ -55,64 +58,57 @@ async function run() {
5558 `${username}@users.noreply.github.com`,
5659 ]);
5760 core.debug('Configured git user.name/user.email');
58- // Create the oprhan github-meta branch if it doesn't exist
59- const branch = core.getInput('branch');
60- const branchExists = await exec_1.exec('git', [
61- 'fetch',
62- 'origin',
63- branch,
64- '--depth',
65- '1',
66- ]);
67- if (branchExists !== 0) {
68- core.info(`No ${branch} branch exists, creating...`);
69- await exec_1.exec('git', ['checkout', '--orphan', branch]);
70- await exec_1.exec('git', ['rm', '-rf', '.']);
71- await exec_1.exec('git', [
72- 'commit',
73- '--allow-empty',
74- '-m',
75- `Creating ${branch} branch`,
76- ]);
77- }
78- else {
79- core.info(`Checking out ${branch}`);
80- await exec_1.exec('git', ['checkout', '-t', `origin/${branch}`]);
81- }
82- // open the database
83- const db = await sqlite_1.open({
84- filename: dbfile,
85- driver: sqlite3_1.default.Database,
86- });
87- // create tables if they don't exist
88- await db.run(`
61+ core.endGroup();
62+ const eventName = github.context.eventName;
63+ if (!events.includes(eventName)) {
64+ throw new Error(`Unsupported event type: ${eventName}`);
65+ }
66+ // Actions can be triggered in parallel
67+ // As a result, several invocations of this code might be
68+ // executing right now.
69+ // We could figure out how to merge sqlite databases; there
70+ // is even some prior art in https://github.com/cannadayr/git-sqlite
71+ // The simple approach of "if our push is refused, pull and try again"
72+ // is probably going to be sufficient.
73+ while (true) {
74+ // open the database
75+ const db = await sqlite_1.open({
76+ filename: dbfile,
77+ driver: sqlite3_1.default.Database,
78+ });
79+ // create tables if they don't exist
80+ await db.run(`
8981 CREATE TABLE IF NOT EXISTS events (
90- id INTEGER PRIMARY KEY,
91- timestamp TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP ,
82+ id TEXT PRIMARY KEY,
83+ timestamp TEXT NOT NULL,
9284 kind TEXT NOT NULL,
9385 event TEXT NOT NULL
9486 );`);
95- core.endGroup();
96- core.startGroup('Capture event');
97- for await (const e of events) {
98- core.debug(`Checking for "${e}" event...`);
99- if (github.context.eventName !== e) {
100- // not this event
101- continue;
102- }
103- await db.run('INSERT INTO events (kind, event) values (:e, :payload)', {
104- ':e': e,
87+ await db.run('INSERT INTO events (id, timestamp, kind, event) values (:id, :timestamp, :e, :payload)', {
88+ ':id': id,
89+ ':timestamp': now,
90+ ':e': eventName,
10591 ':payload': JSON.stringify(github.context.payload),
10692 });
107- core.info(`Captured ${e} event`);
93+ await db.close();
94+ await exec_1.exec('git', ['add', dbfile]);
95+ await exec_1.exec('git', [
96+ 'commit',
97+ '-m',
98+ `Capturing event ${eventName} (id: ${id})`,
99+ ]);
100+ const code = await exec_1.exec('git', ['push']);
101+ if (code === 0) {
102+ // success! We're finished.
103+ core.info('Success!');
104+ break;
105+ }
106+ else {
107+ core.info('Retrying because of conflicts...');
108+ await exec_1.exec('git', ['reset', '--hard', 'HEAD']);
109+ await exec_1.exec('git', ['pull']);
110+ }
108111 }
109- core.endGroup();
110- core.startGroup('Commit and close db');
111- await db.close();
112- await exec_1.exec('git', ['add', dbfile]);
113- await exec_1.exec('git', ['commit', '-m', 'Adding data to repo']);
114- await exec_1.exec('git', ['push', 'origin', branch]);
115- core.endGroup();
116112}
117113run().catch(error => {
118114 core.setFailed('Workflow failed! ' + error.message);
@@ -20236,6 +20232,106 @@ module.exports = require(__nccwpck_require__.ab + "lib/binding/napi-v3-linux-x64
2023620232module.exports = eval("require")("encoding");
2023720233
2023820234
20235+ /***/ }),
20236+
20237+ /***/ 9140:
20238+ /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
20239+
20240+ let crypto = __nccwpck_require__(6417)
20241+
20242+ let { urlAlphabet } = __nccwpck_require__(3861)
20243+
20244+ // It is best to make fewer, larger requests to the crypto module to
20245+ // avoid system call overhead. So, random numbers are generated in a
20246+ // pool. The pool is a Buffer that is larger than the initial random
20247+ // request size by this multiplier. The pool is enlarged if subsequent
20248+ // requests exceed the maximum buffer size.
20249+ const POOL_SIZE_MULTIPLIER = 32
20250+ let pool, poolOffset
20251+
20252+ let random = bytes => {
20253+ if (!pool || pool.length < bytes) {
20254+ pool = Buffer.allocUnsafe(bytes * POOL_SIZE_MULTIPLIER)
20255+ crypto.randomFillSync(pool)
20256+ poolOffset = 0
20257+ } else if (poolOffset + bytes > pool.length) {
20258+ crypto.randomFillSync(pool)
20259+ poolOffset = 0
20260+ }
20261+
20262+ let res = pool.subarray(poolOffset, poolOffset + bytes)
20263+ poolOffset += bytes
20264+ return res
20265+ }
20266+
20267+ let customRandom = (alphabet, size, getRandom) => {
20268+ // First, a bitmask is necessary to generate the ID. The bitmask makes bytes
20269+ // values closer to the alphabet size. The bitmask calculates the closest
20270+ // `2^31 - 1` number, which exceeds the alphabet size.
20271+ // For example, the bitmask for the alphabet size 30 is 31 (00011111).
20272+ let mask = (2 << (31 - Math.clz32((alphabet.length - 1) | 1))) - 1
20273+ // Though, the bitmask solution is not perfect since the bytes exceeding
20274+ // the alphabet size are refused. Therefore, to reliably generate the ID,
20275+ // the random bytes redundancy has to be satisfied.
20276+
20277+ // Note: every hardware random generator call is performance expensive,
20278+ // because the system call for entropy collection takes a lot of time.
20279+ // So, to avoid additional system calls, extra bytes are requested in advance.
20280+
20281+ // Next, a step determines how many random bytes to generate.
20282+ // The number of random bytes gets decided upon the ID size, mask,
20283+ // alphabet size, and magic number 1.6 (using 1.6 peaks at performance
20284+ // according to benchmarks).
20285+ let step = Math.ceil((1.6 * mask * size) / alphabet.length)
20286+
20287+ return () => {
20288+ let id = ''
20289+ while (true) {
20290+ let bytes = getRandom(step)
20291+ // A compact alternative for `for (let i = 0; i < step; i++)`.
20292+ let i = step
20293+ while (i--) {
20294+ // Adding `|| ''` refuses a random byte that exceeds the alphabet size.
20295+ id += alphabet[bytes[i] & mask] || ''
20296+ if (id.length === size) return id
20297+ }
20298+ }
20299+ }
20300+ }
20301+
20302+ let customAlphabet = (alphabet, size) => customRandom(alphabet, size, random)
20303+
20304+ let nanoid = (size = 21) => {
20305+ let bytes = random(size)
20306+ let id = ''
20307+ // A compact alternative for `for (let i = 0; i < size; i++)`.
20308+ while (size--) {
20309+ // It is incorrect to use bytes exceeding the alphabet size.
20310+ // The following mask reduces the random byte in the 0-255 value
20311+ // range to the 0-63 value range. Therefore, adding hacks, such
20312+ // as empty string fallback or magic numbers, is unneccessary because
20313+ // the bitmask trims bytes down to the alphabet size.
20314+ id += urlAlphabet[bytes[size] & 63]
20315+ }
20316+ return id
20317+ }
20318+
20319+ module.exports = { nanoid, customAlphabet, customRandom, urlAlphabet, random }
20320+
20321+
20322+ /***/ }),
20323+
20324+ /***/ 3861:
20325+ /***/ ((module) => {
20326+
20327+ // This alphabet uses `A-Za-z0-9_-` symbols. The genetic algorithm helped
20328+ // optimize the gzip compression for this alphabet.
20329+ let urlAlphabet =
20330+ 'ModuleSymbhasOwnPr-0123456789ABCDEFGHNRVfgctiUvz_KqYTJkLxpZXIjQW'
20331+
20332+ module.exports = { urlAlphabet }
20333+
20334+
2023920335/***/ }),
2024020336
2024120337/***/ 282:
@@ -20278,6 +20374,14 @@ module.exports = require("child_process");;
2027820374
2027920375/***/ }),
2028020376
20377+ /***/ 6417:
20378+ /***/ ((module) => {
20379+
20380+ "use strict";
20381+ module.exports = require("crypto");;
20382+
20383+ /***/ }),
20384+
2028120385/***/ 8614:
2028220386/***/ ((module) => {
2028320387
0 commit comments