@ronaldphilipsen/local-action 0.0.0-stage → 7.1.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/.checkov.yml +3 -0
- package/.env.example +379 -0
- package/.github/codeql/codeql-config.yml +7 -0
- package/.github/copilot-instructions.md +79 -0
- package/.github/dependabot.yml +32 -0
- package/.github/workflows/codeql-analysis.yml +53 -0
- package/.github/workflows/continuous-delivery.yml +93 -0
- package/.github/workflows/continuous-integration.yml +382 -0
- package/.github/workflows/linter.yml +47 -0
- package/.github/workflows/release.yaml +99 -0
- package/.github/workflows/version-check.yml +44 -0
- package/.grype.yml +151 -0
- package/.markdown-lint.yml +7 -0
- package/.mega-linter.yml +188 -0
- package/.node-version +1 -0
- package/.prettierignore +4 -0
- package/.prettierrc.yml +14 -0
- package/.vscode/launch.json +15 -0
- package/.vscode/mcp.json +9 -0
- package/.vscode/settings.json +15 -0
- package/.vscode/tasks.json +51 -0
- package/.yaml-lint.yml +10 -0
- package/CHANGELOG.md +75 -0
- package/CODEOWNERS +3 -0
- package/CODE_OF_CONDUCT.md +74 -0
- package/CONTRIBUTING.md +140 -0
- package/LICENSE +21 -0
- package/README.md +285 -2
- package/SECURITY.md +42 -0
- package/SUPPORT.md +19 -0
- package/__fixtures__/@actions/core.ts +14 -0
- package/__fixtures__/@actions/exec.ts +9 -0
- package/__fixtures__/@actions/github.ts +3 -0
- package/__fixtures__/@actions/http-client.ts +9 -0
- package/__fixtures__/@actions/io.ts +9 -0
- package/__fixtures__/@octokit/rest.ts +18 -0
- package/__fixtures__/crypto.ts +7 -0
- package/__fixtures__/fs.ts +27 -0
- package/__fixtures__/javascript/no-export/.env.fixture +2 -0
- package/__fixtures__/javascript/no-export/action.yml +16 -0
- package/__fixtures__/javascript/no-export/node_modules/.gitkeep +0 -0
- package/__fixtures__/javascript/no-export/package.json +12 -0
- package/__fixtures__/javascript/no-export/src/index.js +0 -0
- package/__fixtures__/javascript/no-export/src/main.js +0 -0
- package/__fixtures__/javascript/no-import/.env.fixture +2 -0
- package/__fixtures__/javascript/no-import/action.yml +16 -0
- package/__fixtures__/javascript/no-import/node_modules/.gitkeep +0 -0
- package/__fixtures__/javascript/no-import/package.json +12 -0
- package/__fixtures__/javascript/no-import/src/index.js +3 -0
- package/__fixtures__/javascript/no-import/src/main.js +7 -0
- package/__fixtures__/javascript/success/.env.fixture +2 -0
- package/__fixtures__/javascript/success/action.yml +16 -0
- package/__fixtures__/javascript/success/node_modules/.gitkeep +0 -0
- package/__fixtures__/javascript/success/package.json +12 -0
- package/__fixtures__/javascript/success/post/index.js +3 -0
- package/__fixtures__/javascript/success/post/main.js +13 -0
- package/__fixtures__/javascript/success/pre/index.js +3 -0
- package/__fixtures__/javascript/success/pre/main.js +13 -0
- package/__fixtures__/javascript/success/src/index.js +3 -0
- package/__fixtures__/javascript/success/src/main.js +13 -0
- package/__fixtures__/javascript-esm/no-import/.env.fixture +2 -0
- package/__fixtures__/javascript-esm/no-import/action.yml +16 -0
- package/__fixtures__/javascript-esm/no-import/node_modules/.gitkeep +0 -0
- package/__fixtures__/javascript-esm/no-import/package.json +13 -0
- package/__fixtures__/javascript-esm/no-import/src/index.js +3 -0
- package/__fixtures__/javascript-esm/no-import/src/main.js +7 -0
- package/__fixtures__/javascript-esm/success/.env.fixture +2 -0
- package/__fixtures__/javascript-esm/success/action.yml +16 -0
- package/__fixtures__/javascript-esm/success/node_modules/.gitkeep +0 -0
- package/__fixtures__/javascript-esm/success/package.json +13 -0
- package/__fixtures__/javascript-esm/success/post/index.js +3 -0
- package/__fixtures__/javascript-esm/success/post/main.js +13 -0
- package/__fixtures__/javascript-esm/success/pre/index.js +3 -0
- package/__fixtures__/javascript-esm/success/pre/main.js +13 -0
- package/__fixtures__/javascript-esm/success/src/index.js +3 -0
- package/__fixtures__/javascript-esm/success/src/main.js +13 -0
- package/__fixtures__/path.ts +7 -0
- package/__fixtures__/payloads/issue_opened.json +33 -0
- package/__fixtures__/stream/promises.ts +3 -0
- package/__fixtures__/tsconfig-paths.ts +4 -0
- package/__fixtures__/typescript/no-import/.env.fixture +2 -0
- package/__fixtures__/typescript/no-import/action.yml +16 -0
- package/__fixtures__/typescript/no-import/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript/no-import/package.json +15 -0
- package/__fixtures__/typescript/no-import/src/index.ts +3 -0
- package/__fixtures__/typescript/no-import/src/main.ts +3 -0
- package/__fixtures__/typescript/no-import/tsconfig.json +20 -0
- package/__fixtures__/typescript/success/.env.fixture +2 -0
- package/__fixtures__/typescript/success/action.yml +16 -0
- package/__fixtures__/typescript/success/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript/success/package.json +15 -0
- package/__fixtures__/typescript/success/post/index.ts +3 -0
- package/__fixtures__/typescript/success/post/main.ts +9 -0
- package/__fixtures__/typescript/success/pre/index.ts +3 -0
- package/__fixtures__/typescript/success/pre/main.ts +9 -0
- package/__fixtures__/typescript/success/src/index.ts +3 -0
- package/__fixtures__/typescript/success/src/main.ts +9 -0
- package/__fixtures__/typescript/success/tsconfig.json +20 -0
- package/__fixtures__/typescript/success-yaml/.env.fixture +2 -0
- package/__fixtures__/typescript/success-yaml/action.yaml +16 -0
- package/__fixtures__/typescript/success-yaml/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript/success-yaml/package.json +15 -0
- package/__fixtures__/typescript/success-yaml/post/index.ts +3 -0
- package/__fixtures__/typescript/success-yaml/post/main.ts +9 -0
- package/__fixtures__/typescript/success-yaml/pre/index.ts +3 -0
- package/__fixtures__/typescript/success-yaml/pre/main.ts +9 -0
- package/__fixtures__/typescript/success-yaml/src/index.ts +3 -0
- package/__fixtures__/typescript/success-yaml/src/main.ts +9 -0
- package/__fixtures__/typescript/success-yaml/tsconfig.json +20 -0
- package/__fixtures__/typescript-esm/no-export/.env.fixture +2 -0
- package/__fixtures__/typescript-esm/no-export/action.yml +17 -0
- package/__fixtures__/typescript-esm/no-export/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript-esm/no-export/package.json +17 -0
- package/__fixtures__/typescript-esm/no-export/src/index.ts +0 -0
- package/__fixtures__/typescript-esm/no-export/src/main.ts +0 -0
- package/__fixtures__/typescript-esm/no-export/tsconfig.json +25 -0
- package/__fixtures__/typescript-esm/no-import/.env.fixture +2 -0
- package/__fixtures__/typescript-esm/no-import/action.yml +17 -0
- package/__fixtures__/typescript-esm/no-import/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript-esm/no-import/package.json +17 -0
- package/__fixtures__/typescript-esm/no-import/src/index.ts +3 -0
- package/__fixtures__/typescript-esm/no-import/src/main.ts +3 -0
- package/__fixtures__/typescript-esm/no-import/tsconfig.json +25 -0
- package/__fixtures__/typescript-esm/success/.env.fixture +2 -0
- package/__fixtures__/typescript-esm/success/action.yml +17 -0
- package/__fixtures__/typescript-esm/success/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript-esm/success/package.json +17 -0
- package/__fixtures__/typescript-esm/success/post/index.ts +3 -0
- package/__fixtures__/typescript-esm/success/post/main.ts +9 -0
- package/__fixtures__/typescript-esm/success/pre/index.ts +3 -0
- package/__fixtures__/typescript-esm/success/pre/main.ts +9 -0
- package/__fixtures__/typescript-esm/success/src/index.ts +3 -0
- package/__fixtures__/typescript-esm/success/src/main.ts +9 -0
- package/__fixtures__/typescript-esm/success/tsconfig.json +25 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/.env.fixture +2 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/action.yml +17 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/node_modules/.gitkeep +0 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/package.json +17 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/src/index.ts +3 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/src/main.ts +9 -0
- package/__fixtures__/typescript-esm/tsconfig-comments/tsconfig.json +21 -0
- package/__tests__/command.test.ts +224 -0
- package/__tests__/stubs/artifact/internal/client.test.ts +340 -0
- package/__tests__/stubs/artifact/internal/delete/delete-artifact.test.ts +152 -0
- package/__tests__/stubs/artifact/internal/download/download-artifact.test.ts +119 -0
- package/__tests__/stubs/artifact/internal/find/get-artifact.test.ts +237 -0
- package/__tests__/stubs/artifact/internal/find/list-artifacts.test.ts +218 -0
- package/__tests__/stubs/artifact/internal/find/retry-options.test.ts +54 -0
- package/__tests__/stubs/artifact/internal/shared/config.test.ts +91 -0
- package/__tests__/stubs/artifact/internal/shared/errors.test.ts +38 -0
- package/__tests__/stubs/artifact/internal/shared/user-agent.test.ts +22 -0
- package/__tests__/stubs/artifact/internal/upload/path-and-artifact-name-validation.test.ts +53 -0
- package/__tests__/stubs/artifact/internal/upload/upload-artifact.test.ts +126 -0
- package/__tests__/stubs/artifact/internal/upload/upload-zip-specification.test.ts +49 -0
- package/__tests__/stubs/cache/cache.test.ts +357 -0
- package/__tests__/stubs/cache/errors.test.ts +55 -0
- package/__tests__/stubs/cache/internal/cacheUtils.test.ts +109 -0
- package/__tests__/stubs/cache/internal/constants.test.ts +81 -0
- package/__tests__/stubs/cache/internal/tar.test.ts +129 -0
- package/__tests__/stubs/core/core.test.ts +760 -0
- package/__tests__/stubs/core/path-utils.test.ts +45 -0
- package/__tests__/stubs/core/platform.test.ts +89 -0
- package/__tests__/stubs/core/summary.test.ts +455 -0
- package/__tests__/stubs/env.test.ts +72 -0
- package/__tests__/stubs/github/context.test.ts +73 -0
- package/__tests__/stubs/github/github.test.ts +15 -0
- package/__tests__/stubs/github/internal/utils.test.ts +98 -0
- package/__tests__/stubs/github/utils.test.ts +16 -0
- package/__tests__/utils/config.test.ts +78 -0
- package/__tests__/utils/output.test.ts +32 -0
- package/__tests__/utils/package.test.ts +33 -0
- package/badges/coverage.svg +1 -0
- package/bin/local-action.js +121 -0
- package/docs/create-a-job-summary.md +32 -0
- package/docs/debugging-in-vscode.md +27 -0
- package/docs/img/job-summary.png +0 -0
- package/docs/supported-functionality.md +126 -0
- package/eslint.config.mjs +74 -0
- package/jest.config.ts +41 -0
- package/package.json +93 -4
- package/src/command.ts +171 -0
- package/src/commands/run.ts +616 -0
- package/src/index.ts +21 -0
- package/src/stubs/artifact/artifact.ts +17 -0
- package/src/stubs/artifact/internal/client.ts +400 -0
- package/src/stubs/artifact/internal/delete/delete-artifact.ts +126 -0
- package/src/stubs/artifact/internal/download/download-artifact.ts +309 -0
- package/src/stubs/artifact/internal/find/get-artifact.ts +135 -0
- package/src/stubs/artifact/internal/find/list-artifacts.ts +188 -0
- package/src/stubs/artifact/internal/find/retry-options.ts +57 -0
- package/src/stubs/artifact/internal/shared/config.ts +64 -0
- package/src/stubs/artifact/internal/shared/errors.ts +53 -0
- package/src/stubs/artifact/internal/shared/interfaces.ts +195 -0
- package/src/stubs/artifact/internal/shared/user-agent.ts +13 -0
- package/src/stubs/artifact/internal/upload/path-and-artifact-name-validation.ts +92 -0
- package/src/stubs/artifact/internal/upload/upload-artifact.ts +127 -0
- package/src/stubs/artifact/internal/upload/upload-zip-specification.ts +108 -0
- package/src/stubs/artifact/internal/upload/zip.ts +122 -0
- package/src/stubs/cache/cache.ts +334 -0
- package/src/stubs/cache/errors.ts +31 -0
- package/src/stubs/cache/interfaces.ts +4 -0
- package/src/stubs/cache/internal/cacheUtils.ts +207 -0
- package/src/stubs/cache/internal/constants.ts +45 -0
- package/src/stubs/cache/internal/tar.ts +374 -0
- package/src/stubs/cache/options.ts +91 -0
- package/src/stubs/core/core.ts +743 -0
- package/src/stubs/core/path-utils.ts +39 -0
- package/src/stubs/core/platform.ts +132 -0
- package/src/stubs/core/summary.ts +399 -0
- package/src/stubs/env.ts +40 -0
- package/src/stubs/github/context.ts +94 -0
- package/src/stubs/github/github.ts +29 -0
- package/src/stubs/github/interfaces.ts +52 -0
- package/src/stubs/github/internal/utils.ts +83 -0
- package/src/stubs/github/utils.ts +52 -0
- package/src/types/quibble.d.ts +5 -0
- package/src/types.ts +116 -0
- package/src/utils/config.ts +47 -0
- package/src/utils/output.ts +20 -0
- package/src/utils/package.ts +38 -0
- package/tsconfig.base.json +29 -0
- package/tsconfig.eslint.json +22 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Last Reviewed Commit: 00282d61458d99f725588a9463b9d25dfda51c22
|
|
3
|
+
* Last Reviewed Date: 2026-01-16
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as path from 'path'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Converts the given path to the posix form. On Windows, `\\` will be replaced
|
|
10
|
+
* with `/`.
|
|
11
|
+
*
|
|
12
|
+
* @param pth Path to transform
|
|
13
|
+
* @return Posix path
|
|
14
|
+
*/
|
|
15
|
+
export function toPosixPath(pth: string): string {
|
|
16
|
+
return pth.replace(/[\\]/g, '/')
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Converts the given path to the win32 form. On Linux, `/` will be replaced
|
|
21
|
+
* with `\\`.
|
|
22
|
+
*
|
|
23
|
+
* @param pth Path to transform
|
|
24
|
+
* @return Win32 path
|
|
25
|
+
*/
|
|
26
|
+
export function toWin32Path(pth: string): string {
|
|
27
|
+
return pth.replace(/[/]/g, '\\')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Converts the given path to a platform-specific path. It does this by
|
|
32
|
+
* replacing instances of `/` and `\` with the platform-specific path separator.
|
|
33
|
+
*
|
|
34
|
+
* @param pth The path to platformize
|
|
35
|
+
* @return The platform-specific path
|
|
36
|
+
*/
|
|
37
|
+
export function toPlatformPath(pth: string): string {
|
|
38
|
+
return pth.replace(/[/\\]/g, path.sep)
|
|
39
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Last Reviewed Commit: d402248c459082c3727b5d592f9c44b81d7d9709
|
|
3
|
+
* Last Reviewed Date: 2026-01-16
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as exec from '@actions/exec'
|
|
7
|
+
import os from 'os'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Gets the Windows version and name.
|
|
11
|
+
*
|
|
12
|
+
* @remarks
|
|
13
|
+
*
|
|
14
|
+
* - Exported for testing purposes.
|
|
15
|
+
*
|
|
16
|
+
* @returns Promise with the Windows version and name
|
|
17
|
+
*/
|
|
18
|
+
export const getWindowsInfo = async (): Promise<{
|
|
19
|
+
name: string
|
|
20
|
+
version: string
|
|
21
|
+
}> => {
|
|
22
|
+
const { stdout: version } = await exec.getExecOutput(
|
|
23
|
+
'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Version"',
|
|
24
|
+
undefined,
|
|
25
|
+
{
|
|
26
|
+
silent: true
|
|
27
|
+
}
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
const { stdout: name } = await exec.getExecOutput(
|
|
31
|
+
'powershell -command "(Get-CimInstance -ClassName Win32_OperatingSystem).Caption"',
|
|
32
|
+
undefined,
|
|
33
|
+
{
|
|
34
|
+
silent: true
|
|
35
|
+
}
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
name: name.trim(),
|
|
40
|
+
version: version.trim()
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Gets the macOS version and name.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
*
|
|
49
|
+
* - Exported for testing purposes.
|
|
50
|
+
*
|
|
51
|
+
* @returns Promise with the macOS version and name
|
|
52
|
+
*/
|
|
53
|
+
export const getMacOsInfo = async (): Promise<{
|
|
54
|
+
name: string
|
|
55
|
+
version: string
|
|
56
|
+
}> => {
|
|
57
|
+
const { stdout } = await exec.getExecOutput('sw_vers', undefined, {
|
|
58
|
+
silent: true
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const version = stdout.match(/ProductVersion:\s*(.+)/)?.[1] ?? ''
|
|
62
|
+
const name = stdout.match(/ProductName:\s*(.+)/)?.[1] ?? ''
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
name,
|
|
66
|
+
version
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Gets the Linux version and name.
|
|
72
|
+
*
|
|
73
|
+
* @remarks
|
|
74
|
+
*
|
|
75
|
+
* - Exported for testing purposes.
|
|
76
|
+
*
|
|
77
|
+
* @returns Promise with the Linux version and name
|
|
78
|
+
*/
|
|
79
|
+
export const getLinuxInfo = async (): Promise<{
|
|
80
|
+
name: string
|
|
81
|
+
version: string
|
|
82
|
+
}> => {
|
|
83
|
+
const { stdout } = await exec.getExecOutput(
|
|
84
|
+
'lsb_release',
|
|
85
|
+
['-i', '-r', '-s'],
|
|
86
|
+
{
|
|
87
|
+
silent: true
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
const [name, version] = stdout.trim().split('\n')
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
name,
|
|
95
|
+
version
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const platform = os.platform()
|
|
100
|
+
export const arch = os.arch()
|
|
101
|
+
export const isWindows = platform === 'win32'
|
|
102
|
+
export const isMacOS = platform === 'darwin'
|
|
103
|
+
export const isLinux = platform === 'linux'
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Gets the platform details.
|
|
107
|
+
*
|
|
108
|
+
* @returns Promise with the platform details
|
|
109
|
+
*/
|
|
110
|
+
/* istanbul ignore next */
|
|
111
|
+
export async function getDetails(): Promise<{
|
|
112
|
+
name: string
|
|
113
|
+
platform: string
|
|
114
|
+
arch: string
|
|
115
|
+
version: string
|
|
116
|
+
isWindows: boolean
|
|
117
|
+
isMacOS: boolean
|
|
118
|
+
isLinux: boolean
|
|
119
|
+
}> {
|
|
120
|
+
return {
|
|
121
|
+
...(await (isWindows
|
|
122
|
+
? getWindowsInfo()
|
|
123
|
+
: isMacOS
|
|
124
|
+
? getMacOsInfo()
|
|
125
|
+
: getLinuxInfo())),
|
|
126
|
+
platform,
|
|
127
|
+
arch,
|
|
128
|
+
isWindows,
|
|
129
|
+
isMacOS,
|
|
130
|
+
isLinux
|
|
131
|
+
}
|
|
132
|
+
}
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Last Reviewed Commit: 07242b37a49ef3c3704f429570b3c9e377b72ecb
|
|
3
|
+
* Last Reviewed Date: 2026-01-16
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs'
|
|
7
|
+
import { EOL } from 'os'
|
|
8
|
+
import path from 'path'
|
|
9
|
+
import { CoreMeta } from './core.js'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A row for a summary table.
|
|
13
|
+
*/
|
|
14
|
+
export type SummaryTableRow = (SummaryTableCell | string)[]
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A cell for a summary table row.
|
|
18
|
+
*/
|
|
19
|
+
export interface SummaryTableCell {
|
|
20
|
+
/**
|
|
21
|
+
* Cell content
|
|
22
|
+
*/
|
|
23
|
+
data: string
|
|
24
|
+
/**
|
|
25
|
+
* Render cell as header
|
|
26
|
+
* (optional) default: false
|
|
27
|
+
*/
|
|
28
|
+
header?: boolean
|
|
29
|
+
/**
|
|
30
|
+
* Number of columns the cell extends
|
|
31
|
+
* (optional) default: '1'
|
|
32
|
+
*/
|
|
33
|
+
colspan?: string
|
|
34
|
+
/**
|
|
35
|
+
* Number of rows the cell extends
|
|
36
|
+
* (optional) default: '1'
|
|
37
|
+
*/
|
|
38
|
+
rowspan?: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Summary image options.
|
|
43
|
+
*/
|
|
44
|
+
export interface SummaryImageOptions {
|
|
45
|
+
/**
|
|
46
|
+
* The width of the image in pixels. Must be an integer without a unit.
|
|
47
|
+
* (optional)
|
|
48
|
+
*/
|
|
49
|
+
width?: string
|
|
50
|
+
/**
|
|
51
|
+
* The height of the image in pixels. Must be an integer without a unit.
|
|
52
|
+
* (optional)
|
|
53
|
+
*/
|
|
54
|
+
height?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Summary write options.
|
|
59
|
+
*/
|
|
60
|
+
export interface SummaryWriteOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Replace all existing content in summary file with buffer contents
|
|
63
|
+
* (optional) default: false
|
|
64
|
+
*/
|
|
65
|
+
overwrite?: boolean
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* A class for creating and writing job step summaries.
|
|
70
|
+
*/
|
|
71
|
+
export class Summary {
|
|
72
|
+
/** Output buffer to write to the summary file. */
|
|
73
|
+
private _buffer: string
|
|
74
|
+
|
|
75
|
+
/** The path to the summary file. */
|
|
76
|
+
private _filePath?: string
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Initialize with an empty buffer.
|
|
80
|
+
*/
|
|
81
|
+
constructor() {
|
|
82
|
+
this._buffer = ''
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Finds the summary file path from the environment. Rejects if the
|
|
87
|
+
* environment variable is not set/empty or the file does not exist.
|
|
88
|
+
*
|
|
89
|
+
* @remarks
|
|
90
|
+
*
|
|
91
|
+
* - Uses core metadata to track step summary path.
|
|
92
|
+
*
|
|
93
|
+
* @returns Step summary file path.
|
|
94
|
+
*/
|
|
95
|
+
async filePath(): Promise<string> {
|
|
96
|
+
// Return the current value, if available.
|
|
97
|
+
if (this._filePath) return this._filePath
|
|
98
|
+
|
|
99
|
+
// Throw if the path is not set/empty.
|
|
100
|
+
if (!CoreMeta.stepSummaryPath)
|
|
101
|
+
throw new Error(
|
|
102
|
+
'Unable to find environment variable for $GITHUB_STEP_SUMMARY. Check if your runtime environment supports job summaries.'
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
// Resolve the full path to the file.
|
|
107
|
+
CoreMeta.stepSummaryPath = path.resolve(
|
|
108
|
+
process.cwd(),
|
|
109
|
+
CoreMeta.stepSummaryPath
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
// If the file does not exist, create it. GitHub Actions runners normally
|
|
113
|
+
// create this file automatically. When testing with local-action, we do
|
|
114
|
+
// not know if the file already exists.
|
|
115
|
+
if (!fs.existsSync(CoreMeta.stepSummaryPath))
|
|
116
|
+
fs.writeFileSync(CoreMeta.stepSummaryPath, '', { encoding: 'utf8' })
|
|
117
|
+
|
|
118
|
+
// Test access to the file (read or write).
|
|
119
|
+
fs.accessSync(
|
|
120
|
+
CoreMeta.stepSummaryPath,
|
|
121
|
+
fs.constants.R_OK | fs.constants.W_OK
|
|
122
|
+
)
|
|
123
|
+
} catch {
|
|
124
|
+
throw new Error(
|
|
125
|
+
`Unable to access summary file: '${CoreMeta.stepSummaryPath}'. Check if the file has correct read/write permissions.`
|
|
126
|
+
)
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this._filePath = CoreMeta.stepSummaryPath
|
|
130
|
+
return Promise.resolve(this._filePath)
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Wraps content in the provided HTML tag and adds any specified attributes.
|
|
135
|
+
*
|
|
136
|
+
* @param tag HTML tag to wrap. Example: 'html', 'body', 'div', etc.
|
|
137
|
+
* @param content The content to wrap within the tag.
|
|
138
|
+
* @param attrs A key-value list of HTML attributes to add.
|
|
139
|
+
* @returns Content wrapped in an HTML element.
|
|
140
|
+
*/
|
|
141
|
+
wrap(
|
|
142
|
+
tag: string,
|
|
143
|
+
content: string | null,
|
|
144
|
+
attrs: { [attribute: string]: string } = {}
|
|
145
|
+
): string {
|
|
146
|
+
const htmlAttrs: string = Object.entries(attrs)
|
|
147
|
+
.map(([key, value]) => ` ${key}="${value}"`)
|
|
148
|
+
.join('')
|
|
149
|
+
|
|
150
|
+
return !content
|
|
151
|
+
? `<${tag}${htmlAttrs}>`
|
|
152
|
+
: `<${tag}${htmlAttrs}>${content}</${tag}>`
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Writes the buffer to the summary file and empties the buffer. This can
|
|
157
|
+
* append (default) or overwrite the file.
|
|
158
|
+
*
|
|
159
|
+
* @param options Options for the write operation.
|
|
160
|
+
* @returns A promise that resolves to the Summary instance for chaining.
|
|
161
|
+
*/
|
|
162
|
+
async write(
|
|
163
|
+
options: SummaryWriteOptions = { overwrite: false }
|
|
164
|
+
): Promise<Summary> {
|
|
165
|
+
// Set the function to call based on the overwrite setting.
|
|
166
|
+
const writeFunc = options.overwrite ? fs.writeFileSync : fs.appendFileSync
|
|
167
|
+
|
|
168
|
+
// If the file does not exist, create it. GitHub Actions runners normally
|
|
169
|
+
// create this file automatically. When testing with local-action, we do not
|
|
170
|
+
// know if the file already exists.
|
|
171
|
+
const filePath: string = await this.filePath()
|
|
172
|
+
|
|
173
|
+
// Call the write function.
|
|
174
|
+
writeFunc(filePath, this._buffer, { encoding: 'utf8' })
|
|
175
|
+
|
|
176
|
+
// Empty the buffer.
|
|
177
|
+
return this.emptyBuffer()
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Clears the buffer and summary file.
|
|
182
|
+
*
|
|
183
|
+
* @returns A promise that resolve to the Summary instance for chaining.
|
|
184
|
+
*/
|
|
185
|
+
async clear(): Promise<Summary> {
|
|
186
|
+
return this.emptyBuffer().write({ overwrite: true })
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Returns the current buffer as a string.
|
|
191
|
+
*
|
|
192
|
+
* @returns Current buffer contents.
|
|
193
|
+
*/
|
|
194
|
+
stringify(): string {
|
|
195
|
+
return this._buffer
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Returns `true` the buffer is empty, `false` otherwise.
|
|
200
|
+
*
|
|
201
|
+
* @returns Whether the buffer is empty.
|
|
202
|
+
*/
|
|
203
|
+
isEmptyBuffer(): boolean {
|
|
204
|
+
return this._buffer.length === 0
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Resets the buffer without writing to the summary file.
|
|
209
|
+
*
|
|
210
|
+
* @returns The Summary instance for chaining.
|
|
211
|
+
*/
|
|
212
|
+
emptyBuffer(): Summary {
|
|
213
|
+
this._buffer = ''
|
|
214
|
+
return this
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Adds raw text to the buffer.
|
|
219
|
+
*
|
|
220
|
+
* @param text The content to add.
|
|
221
|
+
* @param addEOL Whether to append `EOL` to the raw text (default: `false`).
|
|
222
|
+
*
|
|
223
|
+
* @returns The Summary instance for chaining.
|
|
224
|
+
*/
|
|
225
|
+
addRaw(text: string, addEOL: boolean = false): Summary {
|
|
226
|
+
this._buffer += text
|
|
227
|
+
return addEOL ? this.addEOL() : this
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Adds the operating system-specific `EOL` marker to the buffer.
|
|
232
|
+
*
|
|
233
|
+
* @returns The Summary instance for chaining.
|
|
234
|
+
*/
|
|
235
|
+
addEOL(): Summary {
|
|
236
|
+
return this.addRaw(EOL)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Adds a code block (\<code\>) to the buffer.
|
|
241
|
+
*
|
|
242
|
+
* @param code Content to render within the code block.
|
|
243
|
+
* @param lang Language to use for syntax highlighting.
|
|
244
|
+
* @returns Summary instance for chaining.
|
|
245
|
+
*/
|
|
246
|
+
addCodeBlock(code: string, lang?: string): Summary {
|
|
247
|
+
return this.addRaw(
|
|
248
|
+
this.wrap('pre', this.wrap('code', code), lang ? { lang } : {})
|
|
249
|
+
).addEOL()
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Adds a list (\<li\>) element to the buffer.
|
|
254
|
+
*
|
|
255
|
+
* @param items List of items to render.
|
|
256
|
+
* @param ordered Whether the list should be ordered.
|
|
257
|
+
* @returns Summary instance for chaining.
|
|
258
|
+
*/
|
|
259
|
+
addList(items: string[], ordered: boolean = false): Summary {
|
|
260
|
+
return this.addRaw(
|
|
261
|
+
this.wrap(
|
|
262
|
+
ordered ? 'ol' : 'ul',
|
|
263
|
+
items.map(item => this.wrap('li', item)).join('')
|
|
264
|
+
)
|
|
265
|
+
).addEOL()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Adds a table (\<table\>) element to the buffer.
|
|
270
|
+
*
|
|
271
|
+
* @param rows Table rows to render.
|
|
272
|
+
* @returns Summary instance for chaining.
|
|
273
|
+
*/
|
|
274
|
+
addTable(rows: SummaryTableRow[]): Summary {
|
|
275
|
+
return this.addRaw(
|
|
276
|
+
this.wrap(
|
|
277
|
+
'table',
|
|
278
|
+
// The table body consists of a list of rows, each with a list of cells.
|
|
279
|
+
rows
|
|
280
|
+
.map(row => {
|
|
281
|
+
const cells: string = row
|
|
282
|
+
.map(cell => {
|
|
283
|
+
// Cell is a string, return as-is.
|
|
284
|
+
if (typeof cell === 'string') return this.wrap('td', cell)
|
|
285
|
+
|
|
286
|
+
// Cell is a SummaryTableCell, extract the data and attributes.
|
|
287
|
+
return this.wrap(cell.header ? 'th' : 'td', cell.data, {
|
|
288
|
+
...(cell.colspan ? { colspan: cell.colspan } : {}),
|
|
289
|
+
...(cell.rowspan ? { rowspan: cell.rowspan } : {})
|
|
290
|
+
})
|
|
291
|
+
})
|
|
292
|
+
.join('')
|
|
293
|
+
|
|
294
|
+
return this.wrap('tr', cells)
|
|
295
|
+
})
|
|
296
|
+
.join('')
|
|
297
|
+
)
|
|
298
|
+
).addEOL()
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/**
|
|
302
|
+
* Adds a details (\<details\>) element to the buffer.
|
|
303
|
+
*
|
|
304
|
+
* @param label Text for the \<summary\> element.
|
|
305
|
+
* @param content Text for the \<details\> container.
|
|
306
|
+
* @returns Summary instance for chaining.
|
|
307
|
+
*/
|
|
308
|
+
addDetails(label: string, content: string): Summary {
|
|
309
|
+
return this.addRaw(
|
|
310
|
+
this.wrap('details', this.wrap('summary', label) + content)
|
|
311
|
+
).addEOL()
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Adds an image (\<img\>) element to the buffer.
|
|
316
|
+
*
|
|
317
|
+
* @param src Path to the image to embed.
|
|
318
|
+
* @param alt Text description of the image.
|
|
319
|
+
* @param options Additional image attributes.
|
|
320
|
+
* @returns Summary instance for chaining.
|
|
321
|
+
*/
|
|
322
|
+
addImage(
|
|
323
|
+
src: string,
|
|
324
|
+
alt: string,
|
|
325
|
+
options: SummaryImageOptions = {}
|
|
326
|
+
): Summary {
|
|
327
|
+
return this.addRaw(
|
|
328
|
+
this.wrap('img', null, {
|
|
329
|
+
src,
|
|
330
|
+
alt,
|
|
331
|
+
...(options.width ? { width: options.width } : {}),
|
|
332
|
+
...(options.height ? { height: options.height } : {})
|
|
333
|
+
})
|
|
334
|
+
).addEOL()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Adds a heading (\<hX\>) element to the buffer.
|
|
339
|
+
*
|
|
340
|
+
* @param text Heading text to render.
|
|
341
|
+
* @param level Heading level. Defaults to `1`.
|
|
342
|
+
* @returns Summary instance for chaining.
|
|
343
|
+
*/
|
|
344
|
+
addHeading(text: string, level: number | string = 1): Summary {
|
|
345
|
+
// If level is a string, attempt to parse it as a number.
|
|
346
|
+
const levelAsNum = typeof level === 'string' ? parseInt(level) : level
|
|
347
|
+
|
|
348
|
+
// If level is less than 1 or greater than 6, default to `h1`.
|
|
349
|
+
const tag =
|
|
350
|
+
Number.isNaN(levelAsNum) || levelAsNum < 1 || levelAsNum > 6
|
|
351
|
+
? 'h1'
|
|
352
|
+
: `h${level}`
|
|
353
|
+
|
|
354
|
+
const element = this.wrap(tag, text)
|
|
355
|
+
return this.addRaw(element).addEOL()
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Adds a horizontal rule (\<hr\>) element to the buffer.
|
|
360
|
+
*
|
|
361
|
+
* @returns Summary instance for chaining.
|
|
362
|
+
*/
|
|
363
|
+
addSeparator(): Summary {
|
|
364
|
+
return this.addRaw(this.wrap('hr', null)).addEOL()
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Adds a line break (\<br\>) to the buffer.
|
|
369
|
+
*
|
|
370
|
+
* @returns Summary instance for chaining.
|
|
371
|
+
*/
|
|
372
|
+
addBreak(): Summary {
|
|
373
|
+
return this.addRaw(this.wrap('br', null)).addEOL()
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* Adds a block quote \<blockquote\> element to the buffer.
|
|
378
|
+
*
|
|
379
|
+
* @param text Quote text to render.
|
|
380
|
+
* @param cite (Optional) Citation URL.
|
|
381
|
+
* @returns Summary instance for chaining.
|
|
382
|
+
*/
|
|
383
|
+
addQuote(text: string, cite?: string): Summary {
|
|
384
|
+
return this.addRaw(
|
|
385
|
+
this.wrap('blockquote', text, cite ? { cite } : {})
|
|
386
|
+
).addEOL()
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Adds an anchor (\<a\>) element to the buffer.
|
|
391
|
+
*
|
|
392
|
+
* @param text Text content to render.
|
|
393
|
+
* @param href Hyperlink to the target.
|
|
394
|
+
* @returns Summary instance for chaining.
|
|
395
|
+
*/
|
|
396
|
+
addLink(text: string, href: string): Summary {
|
|
397
|
+
return this.addRaw(this.wrap('a', text, { href })).addEOL()
|
|
398
|
+
}
|
|
399
|
+
}
|
package/src/stubs/env.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EnvMetadata } from '../types.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Environment Metdata
|
|
5
|
+
*/
|
|
6
|
+
export const EnvMeta: EnvMetadata = {
|
|
7
|
+
actionFile: '',
|
|
8
|
+
actionPath: '',
|
|
9
|
+
artifacts: [],
|
|
10
|
+
caches: {},
|
|
11
|
+
dotenvFile: '',
|
|
12
|
+
entrypoint: '',
|
|
13
|
+
env: {},
|
|
14
|
+
inputs: {},
|
|
15
|
+
outputs: {},
|
|
16
|
+
path: '',
|
|
17
|
+
postEntrypoint: undefined,
|
|
18
|
+
preEntrypoint: undefined
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reset the Environment Metadata
|
|
23
|
+
*
|
|
24
|
+
* Simple convenience function to reset the environment metadata back to initial
|
|
25
|
+
* state.
|
|
26
|
+
*/
|
|
27
|
+
export function ResetEnvMetadata(): void {
|
|
28
|
+
EnvMeta.actionFile = ''
|
|
29
|
+
EnvMeta.actionPath = ''
|
|
30
|
+
EnvMeta.artifacts = []
|
|
31
|
+
EnvMeta.caches = {}
|
|
32
|
+
EnvMeta.dotenvFile = ''
|
|
33
|
+
EnvMeta.entrypoint = ''
|
|
34
|
+
EnvMeta.env = {}
|
|
35
|
+
EnvMeta.inputs = {}
|
|
36
|
+
EnvMeta.outputs = {}
|
|
37
|
+
EnvMeta.path = ''
|
|
38
|
+
EnvMeta.postEntrypoint = undefined
|
|
39
|
+
EnvMeta.preEntrypoint = undefined
|
|
40
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Last Reviewed Commit: faa425440f86f9c16587a19dfb59491253a2c92a
|
|
3
|
+
* Last Reviewed Date: 2026-01-16
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { existsSync, readFileSync } from 'fs'
|
|
7
|
+
import { EOL } from 'os'
|
|
8
|
+
import type { WebhookPayload } from './interfaces.js'
|
|
9
|
+
|
|
10
|
+
export class Context {
|
|
11
|
+
/**
|
|
12
|
+
* Webhook payload object that triggered the workflow
|
|
13
|
+
*/
|
|
14
|
+
payload: WebhookPayload
|
|
15
|
+
|
|
16
|
+
eventName: string
|
|
17
|
+
sha: string
|
|
18
|
+
ref: string
|
|
19
|
+
workflow: string
|
|
20
|
+
action: string
|
|
21
|
+
actor: string
|
|
22
|
+
job: string
|
|
23
|
+
runAttempt: number
|
|
24
|
+
runNumber: number
|
|
25
|
+
runId: number
|
|
26
|
+
apiUrl: string
|
|
27
|
+
serverUrl: string
|
|
28
|
+
graphqlUrl: string
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Hydrate the context from the environment
|
|
32
|
+
*/
|
|
33
|
+
constructor() {
|
|
34
|
+
this.payload = {}
|
|
35
|
+
|
|
36
|
+
/* istanbul ignore next */
|
|
37
|
+
if (process.env.GITHUB_EVENT_PATH) {
|
|
38
|
+
if (existsSync(process.env.GITHUB_EVENT_PATH)) {
|
|
39
|
+
this.payload = JSON.parse(
|
|
40
|
+
readFileSync(process.env.GITHUB_EVENT_PATH, { encoding: 'utf8' })
|
|
41
|
+
)
|
|
42
|
+
} else {
|
|
43
|
+
const path = process.env.GITHUB_EVENT_PATH
|
|
44
|
+
process.stdout.write(`GITHUB_EVENT_PATH ${path} does not exist${EOL}`)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.eventName = process.env.GITHUB_EVENT_NAME as string
|
|
49
|
+
this.sha = process.env.GITHUB_SHA as string
|
|
50
|
+
this.ref = process.env.GITHUB_REF as string
|
|
51
|
+
this.workflow = process.env.GITHUB_WORKFLOW as string
|
|
52
|
+
this.action = process.env.GITHUB_ACTION as string
|
|
53
|
+
this.actor = process.env.GITHUB_ACTOR as string
|
|
54
|
+
this.job = process.env.GITHUB_JOB as string
|
|
55
|
+
this.runAttempt = parseInt(process.env.GITHUB_RUN_ATTEMPT as string, 10)
|
|
56
|
+
this.runNumber = parseInt(process.env.GITHUB_RUN_NUMBER as string, 10)
|
|
57
|
+
this.runId = parseInt(process.env.GITHUB_RUN_ID as string, 10)
|
|
58
|
+
/* istanbul ignore next */
|
|
59
|
+
this.apiUrl = process.env.GITHUB_API_URL ?? 'https://api.github.com'
|
|
60
|
+
/* istanbul ignore next */
|
|
61
|
+
this.serverUrl = process.env.GITHUB_SERVER_URL ?? 'https://github.com'
|
|
62
|
+
/* istanbul ignore next */
|
|
63
|
+
this.graphqlUrl =
|
|
64
|
+
process.env.GITHUB_GRAPHQL_URL ?? 'https://api.github.com/graphql'
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* istanbul ignore next */
|
|
68
|
+
get issue(): { owner: string; repo: string; number: number } {
|
|
69
|
+
const payload = this.payload
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
...this.repo,
|
|
73
|
+
number: (payload.issue || payload.pull_request || payload).number
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* istanbul ignore next */
|
|
78
|
+
get repo(): { owner: string; repo: string } {
|
|
79
|
+
if (process.env.GITHUB_REPOSITORY) {
|
|
80
|
+
const [owner, repo] = process.env.GITHUB_REPOSITORY.split('/')
|
|
81
|
+
return { owner, repo }
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (this.payload.repository)
|
|
85
|
+
return {
|
|
86
|
+
owner: this.payload.repository.owner.login,
|
|
87
|
+
repo: this.payload.repository.name
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
throw new Error(
|
|
91
|
+
"context.repo requires a GITHUB_REPOSITORY environment variable like 'owner/repo'"
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
}
|