diff --git a/README.md b/README.md index a907700..506acef 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,14 @@ actions can be run directly on your workstation. > > This tool currently only supports JavaScript and TypeScript actions! +The following table tracks the versions of the GitHub Actions Toolkit that are +currently implemented by this tool. + +| Package | Version | +| ------------------- | -------- | +| `@actions/artifact` | `2.2.0` | +| `@actions/core` | `1.11.1` | + ## v2 Changes As of version `2.0.0`, the `local-action` tool has been updated to require diff --git a/__fixtures__/exec.ts b/__fixtures__/exec.ts new file mode 100644 index 0000000..411cbe4 --- /dev/null +++ b/__fixtures__/exec.ts @@ -0,0 +1,9 @@ +import { jest } from '@jest/globals' + +export const exec = jest.fn().mockImplementation(() => {}) +export const getExecOutput = jest.fn().mockImplementation(() => {}) + +export default { + exec, + getExecOutput +} diff --git a/__tests__/command.test.ts b/__tests__/command.test.ts index cd318bc..4f1b868 100644 --- a/__tests__/command.test.ts +++ b/__tests__/command.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' import { Command } from 'commander' -import { ResetCoreMetadata } from '../src/stubs/core.js' +import { ResetCoreMetadata } from '../src/stubs/core/core.js' import { ResetEnvMetadata } from '../src/stubs/env.js' const action = jest.fn() diff --git a/__tests__/commands/run.test.ts b/__tests__/commands/run.test.ts index c4ef3a1..81c00ec 100644 --- a/__tests__/commands/run.test.ts +++ b/__tests__/commands/run.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' import * as core from '../../__fixtures__/core.js' -import { ResetCoreMetadata } from '../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../src/stubs/env.js' const quibbleEsm = jest.fn().mockImplementation(() => {}) diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts index 8fd6e38..5c6f359 100644 --- a/__tests__/index.test.ts +++ b/__tests__/index.test.ts @@ -1,5 +1,5 @@ import { jest } from '@jest/globals' -import { ResetCoreMetadata } from '../src/stubs/core.js' +import { ResetCoreMetadata } from '../src/stubs/core/core.js' import { ResetEnvMetadata } from '../src/stubs/env.js' const makeProgram = jest.fn().mockResolvedValue({ diff --git a/__tests__/stubs/artifact/internal/client.test.ts b/__tests__/stubs/artifact/internal/client.test.ts index c840cc5..c86a5ca 100644 --- a/__tests__/stubs/artifact/internal/client.test.ts +++ b/__tests__/stubs/artifact/internal/client.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' import * as core from '../../../../__fixtures__/core.js' -import { ResetCoreMetadata } from '../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../../../src/stubs/env.js' const isGhes = jest.fn().mockReturnValue(false) @@ -58,7 +58,7 @@ jest.unstable_mockModule( deleteArtifactPublic }) ) -jest.unstable_mockModule('../../../../src/stubs/core.js', () => core) +jest.unstable_mockModule('../../../../src/stubs/core/core.js', () => core) const { DefaultArtifactClient } = await import( '../../../../src/stubs/artifact/internal/client.js' diff --git a/__tests__/stubs/artifact/internal/delete/delete-artifact.test.ts b/__tests__/stubs/artifact/internal/delete/delete-artifact.test.ts index 535adc9..6e38021 100644 --- a/__tests__/stubs/artifact/internal/delete/delete-artifact.test.ts +++ b/__tests__/stubs/artifact/internal/delete/delete-artifact.test.ts @@ -1,11 +1,11 @@ import { jest } from '@jest/globals' import * as core from '../../../../../__fixtures__/core.js' import * as fs from '../../../../../__fixtures__/fs.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js' jest.unstable_mockModule('fs', () => fs) -jest.unstable_mockModule('../../../../../src/stubs/core.js', () => core) +jest.unstable_mockModule('../../../../../src/stubs/core/core.js', () => core) const deleteArtifact = await import( '../../../../../src/stubs/artifact/internal/delete/delete-artifact.js' diff --git a/__tests__/stubs/artifact/internal/download/download-artifact.test.ts b/__tests__/stubs/artifact/internal/download/download-artifact.test.ts index e6bc5bc..6d2d123 100644 --- a/__tests__/stubs/artifact/internal/download/download-artifact.test.ts +++ b/__tests__/stubs/artifact/internal/download/download-artifact.test.ts @@ -3,7 +3,7 @@ import * as core from '../../../../../__fixtures__/core.js' import * as crypto from '../../../../../__fixtures__/crypto.js' import * as fs from '../../../../../__fixtures__/fs.js' import * as stream from '../../../../../__fixtures__/stream/promises.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js' const readStream = { @@ -14,7 +14,7 @@ const readStream = { jest.unstable_mockModule('crypto', () => crypto) jest.unstable_mockModule('fs', () => fs) jest.unstable_mockModule('stream/promises', () => stream) -jest.unstable_mockModule('../../../../../src/stubs/core.js', () => core) +jest.unstable_mockModule('../../../../../src/stubs/core/core.js', () => core) const downloadArtifact = await import( '../../../../../src/stubs/artifact/internal/download/download-artifact.js' diff --git a/__tests__/stubs/artifact/internal/find/get-artifact.test.ts b/__tests__/stubs/artifact/internal/find/get-artifact.test.ts index 8c463ae..a9fb180 100644 --- a/__tests__/stubs/artifact/internal/find/get-artifact.test.ts +++ b/__tests__/stubs/artifact/internal/find/get-artifact.test.ts @@ -1,9 +1,9 @@ import { jest } from '@jest/globals' import * as core from '../../../../../__fixtures__/core.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js' -jest.unstable_mockModule('../../../../../src/stubs/core.js', () => core) +jest.unstable_mockModule('../../../../../src/stubs/core/core.js', () => core) const getArtifact = await import( '../../../../../src/stubs/artifact/internal/find/get-artifact.js' diff --git a/__tests__/stubs/artifact/internal/find/list-artifacts.test.ts b/__tests__/stubs/artifact/internal/find/list-artifacts.test.ts index 39b55ba..397f99b 100644 --- a/__tests__/stubs/artifact/internal/find/list-artifacts.test.ts +++ b/__tests__/stubs/artifact/internal/find/list-artifacts.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' import * as core from '../../../../../__fixtures__/core.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js' jest.unstable_mockModule('@actions/core', () => core) diff --git a/__tests__/stubs/artifact/internal/shared/config.test.ts b/__tests__/stubs/artifact/internal/shared/config.test.ts index 36c3e1b..c5a50a2 100644 --- a/__tests__/stubs/artifact/internal/shared/config.test.ts +++ b/__tests__/stubs/artifact/internal/shared/config.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' import { getGitHubWorkspaceDir } from '../../../../../src/stubs/artifact/internal/shared/config.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { ResetEnvMetadata } from '../../../../../src/stubs/env.js' describe('config', () => { diff --git a/__tests__/stubs/artifact/internal/shared/user-agent.test.ts b/__tests__/stubs/artifact/internal/shared/user-agent.test.ts index b55c497..eda04e9 100644 --- a/__tests__/stubs/artifact/internal/shared/user-agent.test.ts +++ b/__tests__/stubs/artifact/internal/shared/user-agent.test.ts @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' import { getUserAgentString } from '../../../../../src/stubs/artifact/internal/shared/user-agent.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { ResetEnvMetadata } from '../../../../../src/stubs/env.js' describe('user-agent', () => { diff --git a/__tests__/stubs/artifact/internal/upload/upload-artifact.test.ts b/__tests__/stubs/artifact/internal/upload/upload-artifact.test.ts index 7af49c5..448ac3b 100644 --- a/__tests__/stubs/artifact/internal/upload/upload-artifact.test.ts +++ b/__tests__/stubs/artifact/internal/upload/upload-artifact.test.ts @@ -4,7 +4,7 @@ import * as core from '../../../../../__fixtures__/core.js' import * as crypto from '../../../../../__fixtures__/crypto.js' import * as fs from '../../../../../__fixtures__/fs.js' import * as stream from '../../../../../__fixtures__/stream/promises.js' -import { ResetCoreMetadata } from '../../../../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js' const validateArtifactName = jest.fn() @@ -27,7 +27,7 @@ const writeStream = { jest.unstable_mockModule('crypto', () => crypto) jest.unstable_mockModule('fs', () => fs) jest.unstable_mockModule('stream/promises', () => stream) -jest.unstable_mockModule('../../../../../src/stubs/core.js', () => core) +jest.unstable_mockModule('../../../../../src/stubs/core/core.js', () => core) jest.unstable_mockModule( '../../../../../src/stubs/artifact/internal/upload/upload-zip-specification.js', () => ({ diff --git a/__tests__/stubs/core-stubs.test.ts b/__tests__/stubs/core/core.test.ts similarity index 94% rename from __tests__/stubs/core-stubs.test.ts rename to __tests__/stubs/core/core.test.ts index f206f32..3d6a972 100644 --- a/__tests__/stubs/core-stubs.test.ts +++ b/__tests__/stubs/core/core.test.ts @@ -1,5 +1,4 @@ import { jest } from '@jest/globals' -import path from 'path' import { CoreMeta, ResetCoreMetadata, @@ -24,13 +23,10 @@ import { setOutput, setSecret, startGroup, - toPlatformPath, - toPosixPath, - toWin32Path, warning -} from '../../src/stubs/core.js' -import { EnvMeta, ResetEnvMetadata } from '../../src/stubs/env.js' -import type { CoreMetadata } from '../../src/types.js' +} from '../../../src/stubs/core/core.js' +import { EnvMeta, ResetEnvMetadata } from '../../../src/stubs/env.js' +import type { CoreMetadata } from '../../../src/types.js' /** Empty CoreMetadata Object */ const empty: CoreMetadata = { @@ -597,33 +593,5 @@ describe('Core', () => { await expect(getIDToken()).rejects.toThrow('Not implemented') }) }) - - describe('toPosixPath()', () => { - it('Returns a POSIX path', () => { - expect(toPosixPath('C:\\Users\\mona\\Desktop')).toEqual( - 'C:/Users/mona/Desktop' - ) - }) - }) - - describe('toWin32Path()', () => { - it('Returns a WIN32 path', () => { - expect(toWin32Path('C:/Users/mona/Desktop')).toEqual( - 'C:\\Users\\mona\\Desktop' - ) - }) - }) - - describe('toPlatformPath()', () => { - it('Returns a platform-specific path', () => { - expect(toPlatformPath('C:/Users/mona/Desktop')).toEqual( - `C:${path.sep}Users${path.sep}mona${path.sep}Desktop` - ) - - expect(toPosixPath('C:\\Users\\mona\\Desktop')).toEqual( - `C:${path.sep}Users${path.sep}mona${path.sep}Desktop` - ) - }) - }) }) }) diff --git a/__tests__/stubs/core/path-utils.test.ts b/__tests__/stubs/core/path-utils.test.ts new file mode 100644 index 0000000..7211a7f --- /dev/null +++ b/__tests__/stubs/core/path-utils.test.ts @@ -0,0 +1,46 @@ +import { jest } from '@jest/globals' +import path from 'path' +import { ResetCoreMetadata } from '../../../src/stubs/core/core.js' +import { + toPlatformPath, + toPosixPath, + toWin32Path +} from '../../../src/stubs/core/path-utils.js' +import { ResetEnvMetadata } from '../../../src/stubs/env.js' + +// Prevent output during tests +jest.spyOn(console, 'log').mockImplementation(() => {}) +jest.spyOn(console, 'table').mockImplementation(() => {}) + +describe('path-utils', () => { + beforeEach(() => { + // Reset metadata + ResetEnvMetadata() + ResetCoreMetadata() + }) + + afterEach(() => { + // Reset all spies + jest.resetAllMocks() + }) + + describe('toWin32Path()', () => { + it('Returns a WIN32 path', () => { + expect(toWin32Path('C:/Users/mona/Desktop')).toEqual( + 'C:\\Users\\mona\\Desktop' + ) + }) + }) + + describe('toPlatformPath()', () => { + it('Returns a platform-specific path', () => { + expect(toPlatformPath('C:/Users/mona/Desktop')).toEqual( + `C:${path.sep}Users${path.sep}mona${path.sep}Desktop` + ) + + expect(toPosixPath('C:\\Users\\mona\\Desktop')).toEqual( + `C:${path.sep}Users${path.sep}mona${path.sep}Desktop` + ) + }) + }) +}) diff --git a/__tests__/stubs/summary-stubs.test.ts b/__tests__/stubs/core/summary.test.ts similarity index 98% rename from __tests__/stubs/summary-stubs.test.ts rename to __tests__/stubs/core/summary.test.ts index 72abc45..8fd8350 100644 --- a/__tests__/stubs/summary-stubs.test.ts +++ b/__tests__/stubs/core/summary.test.ts @@ -2,8 +2,8 @@ import { jest } from '@jest/globals' import fs from 'fs' import { EOL } from 'os' import path from 'path' -import { CoreMeta, ResetCoreMetadata } from '../../src/stubs/core.js' -import { Summary } from '../../src/stubs/summary.js' +import { CoreMeta, ResetCoreMetadata } from '../../../src/stubs/core/core.js' +import { Summary } from '../../../src/stubs/core/summary.js' let summary: Summary = new Summary() diff --git a/__tests__/stubs/env-stubs.test.ts b/__tests__/stubs/env.test.ts similarity index 96% rename from __tests__/stubs/env-stubs.test.ts rename to __tests__/stubs/env.test.ts index d46f8f4..ab70bab 100644 --- a/__tests__/stubs/env-stubs.test.ts +++ b/__tests__/stubs/env.test.ts @@ -1,5 +1,5 @@ import { jest } from '@jest/globals' -import { ResetCoreMetadata } from '../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../src/stubs/core/core.js' import { EnvMeta, ResetEnvMetadata } from '../../src/stubs/env.js' import type { EnvMetadata } from '../../src/types.js' diff --git a/__tests__/utils/output.test.ts b/__tests__/utils/output.test.ts index 449138e..d271201 100644 --- a/__tests__/utils/output.test.ts +++ b/__tests__/utils/output.test.ts @@ -1,5 +1,5 @@ import { jest } from '@jest/globals' -import { ResetCoreMetadata } from '../../src/stubs/core.js' +import { ResetCoreMetadata } from '../../src/stubs/core/core.js' import { ResetEnvMetadata } from '../../src/stubs/env.js' import { printTitle } from '../../src/utils/output.js' diff --git a/docs/supported-functionality.md b/docs/supported-functionality.md index 7317276..80ee968 100644 --- a/docs/supported-functionality.md +++ b/docs/supported-functionality.md @@ -66,7 +66,7 @@ to the `local-action` command. | `toPosixPath()` | :white_check_mark: | | | `toWin32Path()` | :white_check_mark: | | | `toPlatformPath()` | :white_check_mark: | | -| `platform.*` | :no_entry: | | +| `platform.*` | :white_check_mark: | | ## Under Investigation diff --git a/package-lock.json b/package-lock.json index 5286ec1..e8a7467 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@github/local-action", - "version": "2.3.0", + "version": "2.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@github/local-action", - "version": "2.3.0", + "version": "2.4.0", "license": "MIT", "dependencies": { "@actions/artifact": "^2.2.0", diff --git a/package.json b/package.json index c887ce6..6342ee8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@github/local-action", "description": "Local Debugging for GitHub Actions", - "version": "2.3.0", + "version": "2.4.0", "type": "module", "author": "Nick Alteen ", "private": false, diff --git a/src/commands/run.ts b/src/commands/run.ts index 8ce65d8..5b4cc83 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -2,7 +2,7 @@ import { config } from 'dotenv' import { createRequire } from 'module' import quibble from 'quibble' import { ARTIFACT_STUBS } from '../stubs/artifact/artifact.js' -import { CORE_STUBS, CoreMeta } from '../stubs/core.js' +import { CORE_STUBS, CoreMeta } from '../stubs/core/core.js' import { EnvMeta } from '../stubs/env.js' import type { Action } from '../types.js' import { printTitle } from '../utils/output.js' diff --git a/src/stubs/artifact/internal/client.ts b/src/stubs/artifact/internal/client.ts index f50769f..71d06bc 100644 --- a/src/stubs/artifact/internal/client.ts +++ b/src/stubs/artifact/internal/client.ts @@ -1,4 +1,4 @@ -import { warning } from '../../core.js' +import { warning } from '../../core/core.js' import { deleteArtifactInternal, deleteArtifactPublic diff --git a/src/stubs/artifact/internal/delete/delete-artifact.ts b/src/stubs/artifact/internal/delete/delete-artifact.ts index d55a1ec..cbce1d3 100644 --- a/src/stubs/artifact/internal/delete/delete-artifact.ts +++ b/src/stubs/artifact/internal/delete/delete-artifact.ts @@ -6,7 +6,7 @@ import { retry } from '@octokit/plugin-retry' import fs from 'fs' import path from 'path' import { EnvMeta } from '../../../../stubs/env.js' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' import { getArtifactPublic } from '../find/get-artifact.js' import { getRetryOptions } from '../find/retry-options.js' import { diff --git a/src/stubs/artifact/internal/download/download-artifact.ts b/src/stubs/artifact/internal/download/download-artifact.ts index 1d4d6c4..d3983be 100644 --- a/src/stubs/artifact/internal/download/download-artifact.ts +++ b/src/stubs/artifact/internal/download/download-artifact.ts @@ -5,7 +5,7 @@ import path from 'path' import { finished } from 'stream/promises' import unzip from 'unzip-stream' import { EnvMeta } from '../../../../stubs/env.js' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' import { getGitHubWorkspaceDir } from '../shared/config.js' import { ArtifactNotFoundError } from '../shared/errors.js' import type { diff --git a/src/stubs/artifact/internal/find/get-artifact.ts b/src/stubs/artifact/internal/find/get-artifact.ts index c7ce69e..2a4b360 100644 --- a/src/stubs/artifact/internal/find/get-artifact.ts +++ b/src/stubs/artifact/internal/find/get-artifact.ts @@ -4,7 +4,7 @@ import type { OctokitOptions } from '@octokit/core' import { requestLog } from '@octokit/plugin-request-log' import { retry } from '@octokit/plugin-retry' import { EnvMeta } from '../../../../stubs/env.js' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' import { ArtifactNotFoundError, InvalidResponseError diff --git a/src/stubs/artifact/internal/find/list-artifacts.ts b/src/stubs/artifact/internal/find/list-artifacts.ts index edf2487..e0e4f7a 100644 --- a/src/stubs/artifact/internal/find/list-artifacts.ts +++ b/src/stubs/artifact/internal/find/list-artifacts.ts @@ -4,7 +4,7 @@ import type { OctokitOptions } from '@octokit/core' import { requestLog } from '@octokit/plugin-request-log' import { retry } from '@octokit/plugin-retry' import { EnvMeta } from '../../../../stubs/env.js' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' import type { Artifact, ListArtifactsResponse } from '../shared/interfaces.js' import { getUserAgentString } from '../shared/user-agent.js' import { getRetryOptions } from './retry-options.js' diff --git a/src/stubs/artifact/internal/find/retry-options.ts b/src/stubs/artifact/internal/find/retry-options.ts index 61f1c46..eada9f2 100644 --- a/src/stubs/artifact/internal/find/retry-options.ts +++ b/src/stubs/artifact/internal/find/retry-options.ts @@ -5,7 +5,7 @@ import type { OctokitOptions } from '@octokit/core' import type { RequestRequestOptions } from '@octokit/types' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' export type RetryOptions = { doNotRetry?: number[] diff --git a/src/stubs/artifact/internal/upload/path-and-artifact-name-validation.ts b/src/stubs/artifact/internal/upload/path-and-artifact-name-validation.ts index fab338b..34b55f9 100644 --- a/src/stubs/artifact/internal/upload/path-and-artifact-name-validation.ts +++ b/src/stubs/artifact/internal/upload/path-and-artifact-name-validation.ts @@ -3,7 +3,7 @@ */ /* istanbul ignore file */ -import { info } from '../../../core.js' +import { info } from '../../../core/core.js' /** * Invalid characters that cannot be in the artifact name or an uploaded file. Will be rejected diff --git a/src/stubs/artifact/internal/upload/upload-artifact.ts b/src/stubs/artifact/internal/upload/upload-artifact.ts index 1077400..a25ae92 100644 --- a/src/stubs/artifact/internal/upload/upload-artifact.ts +++ b/src/stubs/artifact/internal/upload/upload-artifact.ts @@ -3,7 +3,7 @@ import fs from 'fs' import path from 'path' import { finished } from 'stream/promises' import { EnvMeta } from '../../../../stubs/env.js' -import * as core from '../../../core.ts' +import * as core from '../../../core/core.ts' import { FilesNotFoundError, InvalidResponseError } from '../shared/errors.js' import type { Artifact, diff --git a/src/stubs/artifact/internal/upload/upload-zip-specification.ts b/src/stubs/artifact/internal/upload/upload-zip-specification.ts index 6cc09d4..8361c96 100644 --- a/src/stubs/artifact/internal/upload/upload-zip-specification.ts +++ b/src/stubs/artifact/internal/upload/upload-zip-specification.ts @@ -5,7 +5,7 @@ import * as fs from 'fs' import { normalize, resolve } from 'path' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' import { validateFilePath } from './path-and-artifact-name-validation.js' export interface UploadZipSpecification { diff --git a/src/stubs/artifact/internal/upload/zip.ts b/src/stubs/artifact/internal/upload/zip.ts index 4f16eb5..759b10d 100644 --- a/src/stubs/artifact/internal/upload/zip.ts +++ b/src/stubs/artifact/internal/upload/zip.ts @@ -6,7 +6,7 @@ import archiver from 'archiver' import { realpath } from 'fs/promises' import * as stream from 'stream' -import * as core from '../../../core.js' +import * as core from '../../../core/core.js' import { getUploadChunkSize } from '../shared/config.js' import type { UploadZipSpecification } from './upload-zip-specification.js' diff --git a/src/stubs/core.ts b/src/stubs/core/core.ts similarity index 83% rename from src/stubs/core.ts rename to src/stubs/core/core.ts index 0f173e3..a571934 100644 --- a/src/stubs/core.ts +++ b/src/stubs/core/core.ts @@ -1,10 +1,8 @@ import path from 'path' -import type { - AnnotationProperties, - CoreMetadata, - InputOptions -} from '../types.js' -import { EnvMeta } from './env.js' +import type { CoreMetadata } from '../../types.js' +import { EnvMeta } from '../env.js' +import { toPlatformPath, toPosixPath, toWin32Path } from './path-utils.js' +import * as platform from './platform.js' import { Summary } from './summary.js' export const CORE_STUBS = { @@ -22,6 +20,7 @@ export const CORE_STUBS = { info, isDebug, notice, + platform, saveState, setCommandEcho, setFailed, @@ -29,6 +28,9 @@ export const CORE_STUBS = { setSecret, startGroup, summary: new Summary(), + toPlatformPath, + toPosixPath, + toWin32Path, warning } @@ -73,11 +75,81 @@ export function ResetCoreMetadata(): void { CoreMeta.stepSummaryPath = process.env.GITHUB_STEP_SUMMARY ?? '' } +/** + * @github/local-action Unmodified + * + * Optional properties that can be sent with annotation commands (notice, error, + * and warning). + */ +export type AnnotationProperties = { + /** A title for the annotation. */ + title?: string + + /** The path of the file for which the annotation should be created. */ + file?: string + + /** The start line for the annotation. */ + startLine?: number + + /** + * The end line for the annotation. Defaults to `startLine` when `startLine` + * is provided. + */ + endLine?: number + + /** + * The start column for the annotation. Cannot be sent when `startLine` and + * `endLine` are different values. + */ + startColumn?: number + + /** + * The end column for the annotation. Cannot be sent when `startLine` and + * `endLine` are different values. Defaults to `startColumn` when + * `startColumn` is provided. + */ + endColumn?: number +} + +/** + * @github/local-action Unmodified + * + * Options for getInput. + */ +export type InputOptions = { + /** + * Optional. Whether the input is required. If required and not present, + * will throw. Defaults to false. + */ + required?: boolean + + /** + * Optional. Whether leading/trailing whitespace will be trimmed for the + * input. Defaults to true. + */ + trimWhitespace?: boolean +} + +/** + * @github/local-action Modified + * + * Prepends to the PATH + * + * @param inputPath The path to prepend to the PATH + * @returns void + */ +export function addPath(inputPath: string): void { + EnvMeta.path = `${inputPath}${path.delimiter}${process.env.PATH}` + process.env.PATH = EnvMeta.path +} + //----------------------------------------------------------------------- // Variables //----------------------------------------------------------------------- /** + * @github/local-action Modified + * * Saves an environment variable * * @param name The name of the environment variable @@ -101,6 +173,8 @@ export function exportVariable( } /** + * @github/local-action Modified + * * Register a secret to mask it in logs * * @param secret The value to register @@ -111,17 +185,8 @@ export function setSecret(secret: string): void { } /** - * Prepends to the PATH + * @github/local-action Modified * - * @param inputPath The path to prepend to the PATH - * @returns void - */ -export function addPath(inputPath: string): void { - EnvMeta.path = `${inputPath}${path.delimiter}${process.env.PATH}` - process.env.PATH = EnvMeta.path -} - -/** * Gets the action input from the environment variables * * @param name The name of the input @@ -146,6 +211,8 @@ export function getInput(name: string, options?: InputOptions): string { } /** + * @github/local-action Modified + * * Gets multiline inputs from environment variables * * @param name The name of the input @@ -177,6 +244,8 @@ export function getMultilineInput( } /** + * @github/local-action Modified + * * Gets boolean inputs from environment variables * * @param name The name of the input @@ -209,6 +278,8 @@ export function getBooleanInput(name: string, options?: InputOptions): boolean { } /** + * @github/local-action Modified + * * Saves outputs and logs to the console * * @param name The name of the output @@ -224,6 +295,8 @@ export function setOutput(name: string, value: string): void { } /** + * @github/local-action Modified + * * Enables or disables the echoing of commands into stdout. * * @todo Currently this does nothing. @@ -240,6 +313,8 @@ export function setCommandEcho(enabled: boolean): void { //----------------------------------------------------------------------- /** + * @github/local-action Modified + * * Set the action status to failed * * @param message The message to log @@ -257,6 +332,8 @@ export function setFailed(message: string | Error): void { //----------------------------------------------------------------------- /** + * @github/local-action New + * * Logs a message with optional annotations * * This is used internally by the other logging functions. It doesn't need to be @@ -331,6 +408,8 @@ export function log( } /** + * @github/local-action Modified + * * Returns true if debugging is enabled * * @returns Whether debugging is enabled @@ -340,6 +419,8 @@ export function isDebug(): boolean { } /** + * @github/local-action Modified + * * Logs a debug message to the console * * E.g. `::debug::{message}` @@ -355,6 +436,8 @@ export function debug(message: string): void { } /** + * @github/local-action Modified + * * Logs an error message to the console * * E.g. `::error file={name},line={line},endLine={endLine},title={title}::{message}` @@ -364,7 +447,7 @@ export function debug(message: string): void { * @returns void */ export function error( - message: string, + message: string | Error, properties: AnnotationProperties = { title: undefined, file: undefined, @@ -374,10 +457,17 @@ export function error( endColumn: undefined } ): void { - log('error', message, properties) + log( + 'error', + /* istanbul ignore next */ + message instanceof Error ? message.toString() : message, + properties + ) } /** + * @github/local-action Modified + * * Logs a warning message to the console * * E.g. `::warning file={name},line={line},endLine={endLine},title={title}::{message}` @@ -387,7 +477,7 @@ export function error( * @returns void */ export function warning( - message: string, + message: string | Error, properties: AnnotationProperties = { title: undefined, file: undefined, @@ -397,10 +487,17 @@ export function warning( endColumn: undefined } ): void { - log('warning', message, properties) + log( + 'warning', + /* istanbul ignore next */ + message instanceof Error ? message.toString() : message, + properties + ) } /** + * @github/local-action Modified + * * Logs a notice message to the console * * E.g. `::notice file={name},line={line},endLine={endLine},title={title}::{message}` @@ -410,7 +507,7 @@ export function warning( * @returns void */ export function notice( - message: string, + message: string | Error, properties: AnnotationProperties = { title: undefined, file: undefined, @@ -420,10 +517,17 @@ export function notice( endColumn: undefined } ): void { - log('notice', message, properties) + log( + 'notice', + /* istanbul ignore next */ + message instanceof Error ? message.toString() : message, + properties + ) } /** + * @github/local-action Modified + * * Logs an info message to the console * * E.g. `::info::{message}` @@ -436,6 +540,8 @@ export function info(message: string): void { } /** + * @github/local-action Modified + * * Starts a group of log lines * * @param title The title of the group @@ -453,6 +559,8 @@ export function startGroup(title: string): void { } /** + * @github/local-action Modified + * * Ends a group of log lines * * @param title The title of the group @@ -470,6 +578,8 @@ export function endGroup(): void { } /** + * @github/local-action Unmodified + * * Wraps an asynchronous function call in a group * * @param name The name of the group @@ -497,6 +607,8 @@ export async function group(name: string, fn: () => Promise): Promise { //----------------------------------------------------------------------- /** + * @github/local-action Modified + * * Save the state of the action. * * For testing purposes, this does nothing other than save it to the `state` @@ -514,6 +626,8 @@ export function saveState(name: string, value: unknown): void { } /** + * @github/local-action Modified + * * Get the state for the action. * * For testing purposes, this does nothing other than return the value from the @@ -527,6 +641,8 @@ export function getState(name: string): string { } /** + * @github/local-action Modified + * * Gets an OIDC token * * @todo Implement @@ -538,40 +654,3 @@ export function getState(name: string): string { export async function getIDToken(aud?: string): Promise { throw new Error('Not implemented') } - -//----------------------------------------------------------------------- -// Path exports -//----------------------------------------------------------------------- - -/** - * Converts the given path to the posix form. On Windows, `\\` will be replaced - * with `/`. - * - * @param pth Path to transform - * @return Posix path - */ -export function toPosixPath(pth: string): string { - return pth.replace(/[\\]/g, '/') -} - -/** - * Converts the given path to the win32 form. On Linux, `/` will be replaced - * with `\\`. - * - * @param pth Path to transform - * @return Win32 path - */ -export function toWin32Path(pth: string): string { - return pth.replace(/[/]/g, '\\') -} - -/** - * Converts the given path to a platform-specific path. It does this by - * replacing instances of `/` and `\` with the platform-specific path separator. - * - * @param pth The path to platformize - * @return The platform-specific path - */ -export function toPlatformPath(pth: string): string { - return pth.replace(/[/\\]/g, path.sep) -} diff --git a/src/stubs/core/path-utils.ts b/src/stubs/core/path-utils.ts new file mode 100644 index 0000000..edc468a --- /dev/null +++ b/src/stubs/core/path-utils.ts @@ -0,0 +1,40 @@ +import * as path from 'path' + +/** + * @github/local-action Unmodified + * + * Converts the given path to the posix form. On Windows, `\\` will be replaced + * with `/`. + * + * @param pth Path to transform + * @return Posix path + */ +export function toPosixPath(pth: string): string { + return pth.replace(/[\\]/g, '/') +} + +/** + * @github/local-action Unmodified + * + * Converts the given path to the win32 form. On Linux, `/` will be replaced + * with `\\`. + * + * @param pth Path to transform + * @return Win32 path + */ +export function toWin32Path(pth: string): string { + return pth.replace(/[/]/g, '\\') +} + +/** + * @github/local-action Unmodified + * + * Converts the given path to a platform-specific path. It does this by + * replacing instances of `/` and `\` with the platform-specific path separator. + * + * @param pth The path to platformize + * @return The platform-specific path + */ +export function toPlatformPath(pth: string): string { + return pth.replace(/[/\\]/g, path.sep) +} diff --git a/src/stubs/core/platform.ts b/src/stubs/core/platform.ts new file mode 100644 index 0000000..719a93b --- /dev/null +++ b/src/stubs/core/platform.ts @@ -0,0 +1,96 @@ +/** + * @github/local-action Unmodified + */ +/* istanbul ignore file */ + +import * as exec from '@actions/exec' +import os from 'os' + +const getWindowsInfo = async (): Promise<{ name: string; version: string }> => { + const { stdout: version } = await exec.getExecOutput( + 'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"', + undefined, + { + silent: true + } + ) + + const { stdout: name } = await exec.getExecOutput( + 'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"', + undefined, + { + silent: true + } + ) + + return { + name: name.trim(), + version: version.trim() + } +} + +const getMacOsInfo = async (): Promise<{ + name: string + version: string +}> => { + const { stdout } = await exec.getExecOutput('sw_vers', undefined, { + silent: true + }) + + const version = stdout.match(/ProductVersion:\s*(.+)/)?.[1] ?? '' + const name = stdout.match(/ProductName:\s*(.+)/)?.[1] ?? '' + + return { + name, + version + } +} + +const getLinuxInfo = async (): Promise<{ + name: string + version: string +}> => { + const { stdout } = await exec.getExecOutput( + 'lsb_release', + ['-i', '-r', '-s'], + { + silent: true + } + ) + + const [name, version] = stdout.trim().split('\n') + + return { + name, + version + } +} + +export const platform = os.platform() +export const arch = os.arch() +export const isWindows = platform === 'win32' +export const isMacOS = platform === 'darwin' +export const isLinux = platform === 'linux' + +export async function getDetails(): Promise<{ + name: string + platform: string + arch: string + version: string + isWindows: boolean + isMacOS: boolean + isLinux: boolean +}> { + return { + ...(await (isWindows + ? getWindowsInfo() + : isMacOS + ? getMacOsInfo() + : getLinuxInfo())), + platform, + arch, + isWindows, + isMacOS, + isLinux + } +} diff --git a/src/stubs/summary.ts b/src/stubs/core/summary.ts similarity index 83% rename from src/stubs/summary.ts rename to src/stubs/core/summary.ts index b54681a..f93ee97 100644 --- a/src/stubs/summary.ts +++ b/src/stubs/core/summary.ts @@ -1,13 +1,67 @@ import fs from 'fs' import { EOL } from 'os' import path from 'path' -import type { - SummaryImageOptions, - SummaryTableRow, - SummaryWriteOptions -} from '../types.js' import { CoreMeta } from './core.js' +/** + * @github/local-action Unmodified + * + * A row for a summary table. + */ +export type SummaryTableRow = (SummaryTableCell | string)[] + +/** + * @github/local-action Unmodified + */ +export interface SummaryTableCell { + /** + * Cell content + */ + data: string + /** + * Render cell as header + * (optional) default: false + */ + header?: boolean + /** + * Number of columns the cell extends + * (optional) default: '1' + */ + colspan?: string + /** + * Number of rows the cell extends + * (optional) default: '1' + */ + rowspan?: string +} + +/** + * @github/local-action Unmodified + */ +export interface SummaryImageOptions { + /** + * The width of the image in pixels. Must be an integer without a unit. + * (optional) + */ + width?: string + /** + * The height of the image in pixels. Must be an integer without a unit. + * (optional) + */ + height?: string +} + +/** + * @github/local-action Unmodified + */ +export interface SummaryWriteOptions { + /** + * Replace all existing content in summary file with buffer contents + * (optional) default: false + */ + overwrite?: boolean +} + /** * A class for creating and writing job step summaries. */ @@ -19,6 +73,8 @@ export class Summary { private _filePath?: string /** + * @github/local-action Unmodified + * * Initialize with an empty buffer. */ constructor() { @@ -26,6 +82,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Finds the summary file path from the environment. Rejects if the * environment variable is not set/empty or the file does not exist. * @@ -70,6 +128,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Wraps content in the provided HTML tag and adds any specified attributes. * * @param tag HTML tag to wrap. Example: 'html', 'body', 'div', etc. @@ -92,6 +152,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Writes the buffer to the summary file and empties the buffer. This can * append (default) or overwrite the file. * @@ -117,6 +179,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Clears the buffer and summary file. * * @returns A promise that resolve to the Summary instance for chaining. @@ -126,6 +190,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Returns the current buffer as a string. * * @returns Current buffer contents. @@ -135,6 +201,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Returns `true` the buffer is empty, `false` otherwise. * * @returns Whether the buffer is empty. @@ -144,6 +212,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Resets the buffer without writing to the summary file. * * @returns The Summary instance for chaining. @@ -154,6 +224,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Adds raw text to the buffer. * * @param text The content to add. @@ -167,6 +239,8 @@ export class Summary { } /** + * @github/local-action Unmodified + * * Adds the operating system-specific `EOL` marker to the buffer. * * @returns The Summary instance for chaining. @@ -176,6 +250,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a code block (\) to the buffer. * * @param code Content to render within the code block. @@ -189,6 +265,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a list (\) element to the buffer. * * @param items List of items to render. @@ -205,6 +283,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a table (\) element to the buffer. * * @param rows Table rows to render. @@ -238,6 +318,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a details (\) element to the buffer. * * @param label Text for the \ element. @@ -251,6 +333,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds an image (\) element to the buffer. * * @param src Path to the image to embed. @@ -274,6 +358,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a heading (\) element to the buffer. * * @param text Heading text to render. @@ -295,6 +381,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a horizontal rule (\) element to the buffer. * * @returns Summary instance for chaining. @@ -304,6 +392,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a line break (\) to the buffer. * * @returns Summary instance for chaining. @@ -313,6 +403,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds a block quote \ element to the buffer. * * @param text Quote text to render. @@ -326,6 +418,8 @@ export class Summary { } /** + * @github/local-action Modified + * * Adds an anchor (\) element to the buffer. * * @param text Text content to render. diff --git a/src/types.ts b/src/types.ts index 68abec9..7d3e831 100644 --- a/src/types.ts +++ b/src/types.ts @@ -137,90 +137,3 @@ export type Runs = { /** Conditions for the `post` script to run */ 'post-if'?: () => boolean } - -/** - * Optional properties that can be sent with annotation commands (notice, error, - * and warning). - */ -export type AnnotationProperties = { - /** A title for the annotation. */ - title?: string - - /** The path of the file for which the annotation should be created. */ - file?: string - - /** The start line for the annotation. */ - startLine?: number - - /** - * The end line for the annotation. Defaults to `startLine` when `startLine` - * is provided. - */ - endLine?: number - - /** - * The start column for the annotation. Cannot be sent when `startLine` and - * `endLine` are different values. - */ - startColumn?: number - - /** - * The end column for the annotation. Cannot be sent when `startLine` and - * `endLine` are different values. Defaults to `startColumn` when - * `startColumn` is provided. - */ - endColumn?: number -} - -/** - * Options for getInput. - */ -export type InputOptions = { - /** - * Optional. Whether the input is required. If required and not present, - * will throw. Defaults to false. - */ - required?: boolean - - /** - * Optional. Whether leading/trailing whitespace will be trimmed for the - * input. Defaults to true. - */ - trimWhitespace?: boolean -} - -/** A table cell from a job step summary. */ -export type SummaryTableCell = { - /** Cell content */ - data: string - - /** Optional. Render cell as header. Defaults to `false`. */ - header?: boolean - - /** Optional. Number of columns the cell extends. Defaults to `1`. */ - colspan?: string - - /** Optional. Number of rows the cell extends. Defaults to '1'. */ - rowspan?: string -} - -/** A row for a summary table. */ -export type SummaryTableRow = (SummaryTableCell | string)[] - -/** The formatting options for an image in a job step summary. */ -export type SummaryImageOptions = { - /** Optional. The width of the image in pixels. */ - width?: string - - /** Optional. The height of the image in pixels. */ - height?: string -} - -/** The options for writing a job step summary. */ -export type SummaryWriteOptions = { - /** - * Optional. Replace all existing content in the summary file with the - * contents of the buffer. Defaults to `false`. - */ - overwrite?: boolean -} diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index 4705547..f1c1fe0 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -8,6 +8,7 @@ "__fixtures__/stream/", "__fixtures__/core.ts", "__fixtures__/crypto.ts", + "__fixtures__/exec.ts", "__fixtures__/fs.ts", "__fixtures__/tsconfig-paths.ts", "__tests__",