1
0
Files
stale/src/classes/state/state-cache-storage.ts
T

100 lines
2.7 KiB
TypeScript
Raw Normal View History

2023-06-23 23:13:39 +02:00
import {IStateStorage} from '../../interfaces/state/state-storage';
import fs from 'fs';
import path from 'path';
import os from 'os';
import * as core from '@actions/core';
2023-07-05 11:06:16 +02:00
import {getOctokit} from '@actions/github';
import {retry as octokitRetry} from '@octokit/plugin-retry';
import * as cache from '@actions/cache';
2023-06-23 23:13:39 +02:00
const CACHE_KEY = '_state';
const STATE_FILE = 'state.txt';
2023-07-05 11:06:16 +02:00
const STALE_DIR = '56acbeaa-1fef-4c79-8f84-7565e560fb03';
const mkTempDir = (): string => {
const tmpDir = path.join(os.tmpdir(), STALE_DIR);
fs.mkdirSync(tmpDir, {recursive: true});
return tmpDir;
};
const unlinkSafely = (filePath: string) => {
try {
fs.unlinkSync(filePath);
} catch (foo) {
/* ignore */
}
};
const resetCacheWithOctokit = async (cacheKey: string): Promise<void> => {
const token = core.getInput('repo-token');
const client = getOctokit(token, undefined, octokitRetry);
// TODO: better way to get repository?
const repo = process.env['GITHUB_REPOSITORY'];
core.debug(`remove cache "${cacheKey}"`);
try {
// TODO: replace with client.rest.
await client.request(
`DELETE /repos/${repo}/actions/caches?key=${cacheKey}`
);
} catch (error) {
if (error.status) {
core.debug(`Cache ${cacheKey} does not exist`);
} else {
throw error;
}
}
};
2023-06-23 23:13:39 +02:00
export class StateCacheStorage implements IStateStorage {
async save(serializedState: string): Promise<void> {
2023-07-05 11:06:16 +02:00
const tmpDir = mkTempDir();
const filePath = path.join(tmpDir, STATE_FILE);
fs.writeFileSync(filePath, serializedState);
2023-06-23 23:13:39 +02:00
try {
2023-07-05 11:06:16 +02:00
await resetCacheWithOctokit(CACHE_KEY);
const fileSize = fs.statSync(filePath).size;
if (fileSize === 0) {
2023-07-05 16:46:04 +02:00
core.info(`the state will be removed`);
2023-07-05 11:06:16 +02:00
return;
}
await cache.saveCache([path.dirname(filePath)], CACHE_KEY);
2023-06-23 23:13:39 +02:00
} catch (error) {
core.warning(
`Saving the state was not successful due to "${
error.message || 'unknown reason'
}"`
);
2023-07-05 11:06:16 +02:00
} finally {
unlinkSafely(filePath);
2023-06-23 23:13:39 +02:00
}
}
async restore(): Promise<string> {
2023-07-05 16:42:40 +02:00
const tmpDir = mkTempDir();
const filePath = path.join(tmpDir, STATE_FILE);
unlinkSafely(filePath);
2023-06-23 23:13:39 +02:00
try {
2023-07-05 16:42:40 +02:00
await cache.restoreCache([path.dirname(filePath)], CACHE_KEY);
2023-07-05 11:06:16 +02:00
2023-07-05 16:42:40 +02:00
if (!fs.existsSync(filePath)) {
2023-06-23 23:13:39 +02:00
core.info(
2023-07-04 18:29:58 +02:00
'The stored state has not been found, probably because of the very first run or the previous run failed'
2023-06-23 23:13:39 +02:00
);
return '';
}
return fs.readFileSync(path.join(tmpDir, STATE_FILE), {
encoding: 'utf8'
});
} catch (error) {
core.warning(
`Restoring the state was not successful due to "${
error.message || 'unknown reason'
}"`
);
return '';
}
}
}