use runner's RUNNER_TEMP for temp directory (#75)

* use runner tempdir

* fix tests etc

* feedback

* ran npm install before generating dist
This commit is contained in:
Edwin Sirko
2024-02-02 13:05:08 -05:00
parent ebbc8c8d58
commit b80af95dd0
7 changed files with 50 additions and 106 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
name: E2E Test name: E2E Test
on: on:
pull_request: workflow_dispatch:
permissions: {} permissions: {}
+28 -40
View File
@@ -10,12 +10,13 @@ describe('stageActionFiles', () => {
let stagingDir: string let stagingDir: string
beforeEach(() => { beforeEach(() => {
sourceDir = fsHelper.createTempDir() process.env.RUNNER_TEMP = '/tmp'
sourceDir = fsHelper.createTempDir('source')
fs.mkdirSync(`${sourceDir}/src`) fs.mkdirSync(`${sourceDir}/src`)
fs.writeFileSync(`${sourceDir}/src/main.js`, fileContent) fs.writeFileSync(`${sourceDir}/src/main.js`, fileContent)
fs.writeFileSync(`${sourceDir}/src/other.js`, fileContent) fs.writeFileSync(`${sourceDir}/src/other.js`, fileContent)
stagingDir = fsHelper.createTempDir() stagingDir = fsHelper.createTempDir('staging')
}) })
afterEach(() => { afterEach(() => {
@@ -67,36 +68,40 @@ describe('stageActionFiles', () => {
}) })
describe('createArchives', () => { describe('createArchives', () => {
let tmpDir: string let stageDir: string
let distDir: string let archiveDir: string
beforeAll(() => { beforeAll(() => {
distDir = fsHelper.createTempDir() process.env.RUNNER_TEMP = '/tmp'
fs.writeFileSync(`${distDir}/hello.txt`, fileContent) stageDir = fsHelper.createTempDir('staging')
fs.writeFileSync(`${distDir}/world.txt`, fileContent) fs.writeFileSync(`${stageDir}/hello.txt`, fileContent)
fs.writeFileSync(`${stageDir}/world.txt`, fileContent)
}) })
beforeEach(() => { beforeEach(() => {
tmpDir = fsHelper.createTempDir() archiveDir = fsHelper.createTempDir('archive')
}) })
afterEach(() => { afterEach(() => {
fs.rmSync(tmpDir, { recursive: true }) fs.rmSync(archiveDir, { recursive: true })
}) })
afterAll(() => { afterAll(() => {
fs.rmSync(distDir, { recursive: true }) fs.rmSync(stageDir, { recursive: true })
}) })
it('creates archives', async () => { it('creates archives', async () => {
const { zipFile, tarFile } = await fsHelper.createArchives(distDir, tmpDir) const { zipFile, tarFile } = await fsHelper.createArchives(
stageDir,
archiveDir
)
expect(zipFile.path).toEqual(`${tmpDir}/archive.zip`) expect(zipFile.path).toEqual(`${archiveDir}/archive.zip`)
expect(fs.existsSync(zipFile.path)).toEqual(true) expect(fs.existsSync(zipFile.path)).toEqual(true)
expect(fs.statSync(zipFile.path).size).toBeGreaterThan(0) expect(fs.statSync(zipFile.path).size).toBeGreaterThan(0)
expect(zipFile.sha256.startsWith('sha256:')).toEqual(true) expect(zipFile.sha256.startsWith('sha256:')).toEqual(true)
expect(tarFile.path).toEqual(`${tmpDir}/archive.tar.gz`) expect(tarFile.path).toEqual(`${archiveDir}/archive.tar.gz`)
expect(fs.existsSync(tarFile.path)).toEqual(true) expect(fs.existsSync(tarFile.path)).toEqual(true)
expect(fs.statSync(tarFile.path).size).toBeGreaterThan(0) expect(fs.statSync(tarFile.path).size).toBeGreaterThan(0)
expect(tarFile.sha256.startsWith('sha256:')).toEqual(true) expect(tarFile.sha256.startsWith('sha256:')).toEqual(true)
@@ -150,20 +155,20 @@ describe('createTempDir', () => {
} }
}) })
it('creates a temporary directory in the OS temporary dir', () => { it('creates a temporary directory', () => {
const tmpDir = fsHelper.createTempDir() process.env.RUNNER_TEMP = '/tmp'
dirs.push(tmpDir) const tmpDir = fsHelper.createTempDir('subdir')
expect(fs.existsSync(tmpDir)).toEqual(true) expect(fs.existsSync(tmpDir)).toEqual(true)
expect(fs.statSync(tmpDir).isDirectory()).toEqual(true) expect(fs.statSync(tmpDir).isDirectory()).toEqual(true)
expect(tmpDir.startsWith(os.tmpdir())).toEqual(true)
}) })
it('creates a unique temporary directory', () => { it('creates a unique temporary directory', () => {
const dir1 = fsHelper.createTempDir() process.env.RUNNER_TEMP = '/tmp'
const dir1 = fsHelper.createTempDir('dir1')
dirs.push(dir1) dirs.push(dir1)
const dir2 = fsHelper.createTempDir() const dir2 = fsHelper.createTempDir('dir2')
dirs.push(dir2) dirs.push(dir2)
expect(dir1).not.toEqual(dir2) expect(dir1).not.toEqual(dir2)
@@ -174,7 +179,8 @@ describe('isDirectory', () => {
let dir: string let dir: string
beforeEach(() => { beforeEach(() => {
dir = fsHelper.createTempDir() process.env.RUNNER_TEMP = '/tmp'
dir = fsHelper.createTempDir('subdir')
}) })
afterEach(() => { afterEach(() => {
@@ -196,7 +202,8 @@ describe('readFileContents', () => {
let dir: string let dir: string
beforeEach(() => { beforeEach(() => {
dir = fsHelper.createTempDir() process.env.RUNNER_TEMP = '/tmp'
dir = fsHelper.createTempDir('subdir')
}) })
afterEach(() => { afterEach(() => {
@@ -210,22 +217,3 @@ describe('readFileContents', () => {
expect(fsHelper.readFileContents(tempFile).toString()).toEqual(fileContent) expect(fsHelper.readFileContents(tempFile).toString()).toEqual(fileContent)
}) })
}) })
describe('removeDir', () => {
let dir: string
beforeEach(() => {
dir = fsHelper.createTempDir()
})
afterEach(() => {
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true })
}
})
it('removes a directory', () => {
fsHelper.removeDir(dir)
expect(fs.existsSync(dir)).toEqual(false)
})
})
+1 -9
View File
@@ -21,7 +21,6 @@ let setOutputMock: jest.SpyInstance
// Mock the filesystem helper // Mock the filesystem helper
let createTempDirMock: jest.SpyInstance let createTempDirMock: jest.SpyInstance
let createArchivesMock: jest.SpyInstance let createArchivesMock: jest.SpyInstance
let removeDirMock: jest.SpyInstance
let stageActionFilesMock: jest.SpyInstance let stageActionFilesMock: jest.SpyInstance
// Mock the GHCR Client // Mock the GHCR Client
@@ -46,7 +45,6 @@ describe('run', () => {
createArchivesMock = jest createArchivesMock = jest
.spyOn(fsHelper, 'createArchives') .spyOn(fsHelper, 'createArchives')
.mockImplementation() .mockImplementation()
removeDirMock = jest.spyOn(fsHelper, 'removeDir').mockImplementation()
stageActionFilesMock = jest stageActionFilesMock = jest
.spyOn(fsHelper, 'stageActionFiles') .spyOn(fsHelper, 'stageActionFiles')
.mockImplementation() .mockImplementation()
@@ -327,7 +325,7 @@ describe('run', () => {
} }
} }
createTempDirMock.mockImplementation(() => '/tmp/test') createTempDirMock.mockImplementation(() => '/tmp/test/subdir')
createArchivesMock.mockImplementation(() => { createArchivesMock.mockImplementation(() => {
return { return {
@@ -382,11 +380,5 @@ describe('run', () => {
'package-manifest-sha', 'package-manifest-sha',
'sha256:my-test-digest' 'sha256:my-test-digest'
) )
// Expect all the temp files to be cleaned up
expect(removeDirMock).toHaveBeenCalledWith('/tmp/test')
expect(removeDirMock).toHaveBeenCalledTimes(
createTempDirMock.mock.calls.length
)
}) })
}) })
+1 -1
View File
@@ -1 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 94.25%"><title>Coverage: 94.25%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#4c1"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">94.25%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">94.25%</text></g></svg> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="116" height="20" role="img" aria-label="Coverage: 93.96%"><title>Coverage: 93.96%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="116" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="63" height="20" fill="#555"/><rect x="63" width="53" height="20" fill="#4c1"/><rect width="116" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="325" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="530">Coverage</text><text x="325" y="140" transform="scale(.1)" fill="#fff" textLength="530">Coverage</text><text aria-hidden="true" x="885" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">93.96%</text><text x="885" y="140" transform="scale(.1)" fill="#fff" textLength="430">93.96%</text></g></svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Generated Vendored
+7 -25
View File
@@ -74379,32 +74379,25 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod }; return (mod && mod.__esModule) ? mod : { "default": mod };
}; };
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.stageActionFiles = exports.readFileContents = exports.isDirectory = exports.createArchives = exports.removeDir = exports.createTempDir = void 0; exports.stageActionFiles = exports.readFileContents = exports.isDirectory = exports.createArchives = exports.createTempDir = void 0;
const fs = __importStar(__nccwpck_require__(57147)); const fs = __importStar(__nccwpck_require__(57147));
const fs_extra_1 = __importDefault(__nccwpck_require__(5630)); const fs_extra_1 = __importDefault(__nccwpck_require__(5630));
const path = __importStar(__nccwpck_require__(71017)); const path = __importStar(__nccwpck_require__(71017));
const tar = __importStar(__nccwpck_require__(74674)); const tar = __importStar(__nccwpck_require__(74674));
const archiver = __importStar(__nccwpck_require__(43084)); const archiver = __importStar(__nccwpck_require__(43084));
const crypto = __importStar(__nccwpck_require__(6113)); const crypto = __importStar(__nccwpck_require__(6113));
const os = __importStar(__nccwpck_require__(22037)); function createTempDir(subDirName) {
function createTempDir() { const runnerTempDir = process.env.RUNNER_TEMP || '';
const randomDirName = crypto.randomBytes(4).toString('hex'); const tempDir = path.join(runnerTempDir, subDirName);
const tempDir = path.join(os.tmpdir(), randomDirName);
if (!fs.existsSync(tempDir)) { if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir); fs.mkdirSync(tempDir);
} }
return tempDir; return tempDir;
} }
exports.createTempDir = createTempDir; exports.createTempDir = createTempDir;
function removeDir(dir) {
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true });
}
}
exports.removeDir = removeDir;
// Creates both a tar.gz and zip archive of the given directory and returns the paths to both archives (stored in the provided target directory) // Creates both a tar.gz and zip archive of the given directory and returns the paths to both archives (stored in the provided target directory)
// as well as the size/sha256 hash of each file. // as well as the size/sha256 hash of each file.
async function createArchives(distPath, archiveTargetPath = createTempDir()) { async function createArchives(distPath, archiveTargetPath) {
const zipPath = path.join(archiveTargetPath, `archive.zip`); const zipPath = path.join(archiveTargetPath, `archive.zip`);
const tarPath = path.join(archiveTargetPath, `archive.tar.gz`); const tarPath = path.join(archiveTargetPath, `archive.tar.gz`);
const createZipPromise = new Promise((resolve, reject) => { const createZipPromise = new Promise((resolve, reject) => {
@@ -74709,7 +74702,6 @@ const semver_1 = __importDefault(__nccwpck_require__(11383));
* @returns {Promise<void>} Resolves when the action is complete. * @returns {Promise<void>} Resolves when the action is complete.
*/ */
async function run() { async function run() {
const tmpDirs = [];
try { try {
const repository = process.env.GITHUB_REPOSITORY || ''; const repository = process.env.GITHUB_REPOSITORY || '';
if (repository === '') { if (repository === '') {
@@ -74728,12 +74720,10 @@ async function run() {
} }
const semanticVersion = parseSourceSemanticVersion(); const semanticVersion = parseSourceSemanticVersion();
// Create a temporary directory to stage files for packaging in archives // Create a temporary directory to stage files for packaging in archives
const stagedActionFilesDir = fsHelper.createTempDir(); const stagedActionFilesDir = fsHelper.createTempDir('staging');
tmpDirs.push(stagedActionFilesDir);
fsHelper.stageActionFiles('.', stagedActionFilesDir); fsHelper.stageActionFiles('.', stagedActionFilesDir);
// Create a temporary directory to store the archives // Create a temporary directory to store the archives
const archiveDir = fsHelper.createTempDir(); const archiveDir = fsHelper.createTempDir('archive');
tmpDirs.push(archiveDir);
const archives = await fsHelper.createArchives(stagedActionFilesDir, archiveDir); const archives = await fsHelper.createArchives(stagedActionFilesDir, archiveDir);
const { repoId, ownerId } = await api.getRepositoryMetadata(repository, token); const { repoId, ownerId } = await api.getRepositoryMetadata(repository, token);
const manifest = ociContainer.createActionPackageManifest(archives.tarFile, archives.zipFile, repository, repoId, ownerId, sourceCommit, semanticVersion.raw, new Date()); const manifest = ociContainer.createActionPackageManifest(archives.tarFile, archives.zipFile, repository, repoId, ownerId, sourceCommit, semanticVersion.raw, new Date());
@@ -74749,14 +74739,6 @@ async function run() {
if (error instanceof Error) if (error instanceof Error)
core.setFailed(error.message); core.setFailed(error.message);
} }
finally {
// Clean up any temporary directories that exist
for (const tmpDir of tmpDirs) {
if (tmpDir !== '') {
fsHelper.removeDir(tmpDir);
}
}
}
} }
exports.run = run; exports.run = run;
// This action can be triggered by release events or tag push events. // This action can be triggered by release events or tag push events.
+10 -17
View File
@@ -4,11 +4,16 @@ import * as path from 'path'
import * as tar from 'tar' import * as tar from 'tar'
import * as archiver from 'archiver' import * as archiver from 'archiver'
import * as crypto from 'crypto' import * as crypto from 'crypto'
import * as os from 'os'
export function createTempDir(): string { export interface FileMetadata {
const randomDirName = crypto.randomBytes(4).toString('hex') path: string
const tempDir = path.join(os.tmpdir(), randomDirName) size: number
sha256: string
}
export function createTempDir(subDirName: string): string {
const runnerTempDir: string = process.env.RUNNER_TEMP || ''
const tempDir = path.join(runnerTempDir, subDirName)
if (!fs.existsSync(tempDir)) { if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir) fs.mkdirSync(tempDir)
@@ -17,23 +22,11 @@ export function createTempDir(): string {
return tempDir return tempDir
} }
export function removeDir(dir: string): void {
if (fs.existsSync(dir)) {
fs.rmSync(dir, { recursive: true })
}
}
export interface FileMetadata {
path: string
size: number
sha256: string
}
// Creates both a tar.gz and zip archive of the given directory and returns the paths to both archives (stored in the provided target directory) // Creates both a tar.gz and zip archive of the given directory and returns the paths to both archives (stored in the provided target directory)
// as well as the size/sha256 hash of each file. // as well as the size/sha256 hash of each file.
export async function createArchives( export async function createArchives(
distPath: string, distPath: string,
archiveTargetPath: string = createTempDir() archiveTargetPath: string
): Promise<{ zipFile: FileMetadata; tarFile: FileMetadata }> { ): Promise<{ zipFile: FileMetadata; tarFile: FileMetadata }> {
const zipPath = path.join(archiveTargetPath, `archive.zip`) const zipPath = path.join(archiveTargetPath, `archive.zip`)
const tarPath = path.join(archiveTargetPath, `archive.tar.gz`) const tarPath = path.join(archiveTargetPath, `archive.tar.gz`)
+2 -13
View File
@@ -11,8 +11,6 @@ import semver from 'semver'
* @returns {Promise<void>} Resolves when the action is complete. * @returns {Promise<void>} Resolves when the action is complete.
*/ */
export async function run(): Promise<void> { export async function run(): Promise<void> {
const tmpDirs: string[] = []
try { try {
const repository: string = process.env.GITHUB_REPOSITORY || '' const repository: string = process.env.GITHUB_REPOSITORY || ''
if (repository === '') { if (repository === '') {
@@ -34,13 +32,11 @@ export async function run(): Promise<void> {
const semanticVersion = parseSourceSemanticVersion() const semanticVersion = parseSourceSemanticVersion()
// Create a temporary directory to stage files for packaging in archives // Create a temporary directory to stage files for packaging in archives
const stagedActionFilesDir = fsHelper.createTempDir() const stagedActionFilesDir = fsHelper.createTempDir('staging')
tmpDirs.push(stagedActionFilesDir)
fsHelper.stageActionFiles('.', stagedActionFilesDir) fsHelper.stageActionFiles('.', stagedActionFilesDir)
// Create a temporary directory to store the archives // Create a temporary directory to store the archives
const archiveDir = fsHelper.createTempDir() const archiveDir = fsHelper.createTempDir('archive')
tmpDirs.push(archiveDir)
const archives = await fsHelper.createArchives( const archives = await fsHelper.createArchives(
stagedActionFilesDir, stagedActionFilesDir,
archiveDir archiveDir
@@ -82,13 +78,6 @@ export async function run(): Promise<void> {
} catch (error) { } catch (error) {
// Fail the workflow run if an error occurs // Fail the workflow run if an error occurs
if (error instanceof Error) core.setFailed(error.message) if (error instanceof Error) core.setFailed(error.message)
} finally {
// Clean up any temporary directories that exist
for (const tmpDir of tmpDirs) {
if (tmpDir !== '') {
fsHelper.removeDir(tmpDir)
}
}
} }
} }