@ronaldphilipsen/local-action 0.0.0-stage → 7.0.1
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 +100 -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 +277 -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,616 @@
|
|
|
1
|
+
import { parse } from 'comment-json'
|
|
2
|
+
import { config } from 'dotenv'
|
|
3
|
+
import { createRequire } from 'module'
|
|
4
|
+
import { execSync } from 'node:child_process'
|
|
5
|
+
import path from 'path'
|
|
6
|
+
import * as quibble from 'quibble'
|
|
7
|
+
import { loadConfig, register } from 'tsconfig-paths'
|
|
8
|
+
import { fileURLToPath } from 'url'
|
|
9
|
+
import { ARTIFACT_STUBS } from '../stubs/artifact/artifact.js'
|
|
10
|
+
import { CACHE_STUBS } from '../stubs/cache/cache.js'
|
|
11
|
+
import { CORE_STUBS, CoreMeta } from '../stubs/core/core.js'
|
|
12
|
+
import { EnvMeta } from '../stubs/env.js'
|
|
13
|
+
import { Context } from '../stubs/github/context.js'
|
|
14
|
+
import { getOctokit } from '../stubs/github/github.js'
|
|
15
|
+
import type { Action } from '../types.js'
|
|
16
|
+
import { getOSEntrypoints } from '../utils/config.ts'
|
|
17
|
+
import { printTitle } from '../utils/output.js'
|
|
18
|
+
import { isESM } from '../utils/package.js'
|
|
19
|
+
|
|
20
|
+
const require = createRequire(import.meta.url)
|
|
21
|
+
let needsReplug: boolean = false
|
|
22
|
+
|
|
23
|
+
export async function action(
|
|
24
|
+
actionPath: string,
|
|
25
|
+
entrypoint: string,
|
|
26
|
+
dotenvFile: string,
|
|
27
|
+
options: {
|
|
28
|
+
pre: string | undefined
|
|
29
|
+
post: string | undefined
|
|
30
|
+
}
|
|
31
|
+
): Promise<void> {
|
|
32
|
+
const { Chalk } = await import('chalk')
|
|
33
|
+
const chalk = new Chalk()
|
|
34
|
+
const fs = await import('fs')
|
|
35
|
+
const YAML = await import('yaml')
|
|
36
|
+
|
|
37
|
+
if (process.env.TARGET_ACTION_PATH && process.env.TARGET_ACTION_PATH !== '') {
|
|
38
|
+
// Check if the action has a `tsconfig.json` file.
|
|
39
|
+
if (fs.existsSync(`${process.env.TARGET_ACTION_PATH}/tsconfig.json`)) {
|
|
40
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
41
|
+
|
|
42
|
+
// Load the `tsconfig.json` from the action directory.
|
|
43
|
+
const actionTsConfig = parse(
|
|
44
|
+
fs.readFileSync(
|
|
45
|
+
`${process.env.TARGET_ACTION_PATH}/tsconfig.json`,
|
|
46
|
+
'utf-8'
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
// Load the current `tsconfig.json` from the root of this directory.
|
|
51
|
+
loadConfig(__dirname)
|
|
52
|
+
|
|
53
|
+
// Get the paths from the action's `tsconfig.json`, if any.
|
|
54
|
+
// @ts-expect-error comment-json type mismatch
|
|
55
|
+
const paths = actionTsConfig?.compilerOptions?.paths ?? {}
|
|
56
|
+
|
|
57
|
+
// Add any path mappings from the imported action. Replace the base URL with
|
|
58
|
+
// the target action path.
|
|
59
|
+
// @todo Should this take into account the previous `baseUrl` value?
|
|
60
|
+
register({
|
|
61
|
+
baseUrl: process.env.TARGET_ACTION_PATH,
|
|
62
|
+
paths,
|
|
63
|
+
addMatchAll: true
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
CoreMeta.colors = {
|
|
69
|
+
cyan: (msg: string) => console.log(chalk.cyan(msg)),
|
|
70
|
+
blue: (msg: string) => console.log(chalk.blue(msg)),
|
|
71
|
+
gray: (msg: string) => console.log(chalk.gray(msg)),
|
|
72
|
+
green: (msg: string) => console.log(chalk.green(msg)),
|
|
73
|
+
magenta: (msg: string) => console.log(chalk.magenta(msg)),
|
|
74
|
+
red: (msg: string) => console.log(chalk.red(msg)),
|
|
75
|
+
white: (msg: string) => console.log(chalk.white(msg)),
|
|
76
|
+
yellow: (msg: string) => console.log(chalk.yellow(msg))
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const actionType = isESM() ? 'esm' : 'cjs'
|
|
80
|
+
|
|
81
|
+
// Output the configuration
|
|
82
|
+
const startConfig = [
|
|
83
|
+
{
|
|
84
|
+
Field: 'Action Path',
|
|
85
|
+
Value: actionPath
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
Field: 'Entrypoint',
|
|
89
|
+
Value: entrypoint
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
if (options.pre)
|
|
94
|
+
startConfig.push({
|
|
95
|
+
Field: 'Pre Entrypoint',
|
|
96
|
+
Value: options.pre
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
if (options.post)
|
|
100
|
+
startConfig.push({
|
|
101
|
+
Field: 'Post Entrypoint',
|
|
102
|
+
Value: options.post
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
startConfig.push({
|
|
106
|
+
Field: 'Environment File',
|
|
107
|
+
Value: dotenvFile
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
printTitle(CoreMeta.colors.cyan, 'Configuration')
|
|
111
|
+
console.log()
|
|
112
|
+
console.table(startConfig)
|
|
113
|
+
console.log()
|
|
114
|
+
|
|
115
|
+
// Load the environment file
|
|
116
|
+
// @todo Load this into EnvMeta directly? What about secrets...
|
|
117
|
+
config({
|
|
118
|
+
path: path.resolve(process.cwd(), dotenvFile),
|
|
119
|
+
override: true,
|
|
120
|
+
quiet: true
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
// Load action settings
|
|
124
|
+
CoreMeta.stepDebug = process.env.ACTIONS_STEP_DEBUG === 'true'
|
|
125
|
+
CoreMeta.stepSummaryPath = process.env.GITHUB_STEP_SUMMARY ?? ''
|
|
126
|
+
|
|
127
|
+
// Read the action.yml file and parse the expected inputs/outputs
|
|
128
|
+
const actionYaml: Action = YAML.parse(
|
|
129
|
+
fs.readFileSync(EnvMeta.actionFile, { encoding: 'utf8', flag: 'r' })
|
|
130
|
+
) as Action
|
|
131
|
+
|
|
132
|
+
EnvMeta.inputs = actionYaml.inputs || {}
|
|
133
|
+
EnvMeta.outputs = actionYaml.outputs || {}
|
|
134
|
+
|
|
135
|
+
// If the LOCAL_ACTION_CACHE_PATH env var is set, read it to populate the
|
|
136
|
+
// existing caches.
|
|
137
|
+
if (
|
|
138
|
+
process.env.LOCAL_ACTION_CACHE_PATH &&
|
|
139
|
+
process.env.LOCAL_ACTION_CACHE_PATH !== ''
|
|
140
|
+
) {
|
|
141
|
+
const cacheFiles = fs
|
|
142
|
+
.readdirSync(process.env.LOCAL_ACTION_CACHE_PATH)
|
|
143
|
+
.filter(file => file.endsWith('.cache'))
|
|
144
|
+
|
|
145
|
+
// The cache ID will be the next available ID based on existing caches.
|
|
146
|
+
let nextCacheId = 1
|
|
147
|
+
|
|
148
|
+
for (const file of cacheFiles) {
|
|
149
|
+
EnvMeta.caches[nextCacheId] = file
|
|
150
|
+
nextCacheId++
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Output the action metadata
|
|
155
|
+
printTitle(CoreMeta.colors.blue, 'Action Metadata')
|
|
156
|
+
console.log()
|
|
157
|
+
console.table(
|
|
158
|
+
Object.keys(EnvMeta.inputs).map(i => ({
|
|
159
|
+
Input: i,
|
|
160
|
+
Description: EnvMeta.inputs[i].description
|
|
161
|
+
}))
|
|
162
|
+
)
|
|
163
|
+
console.log()
|
|
164
|
+
console.table(
|
|
165
|
+
Object.keys(EnvMeta.outputs).map(i => ({
|
|
166
|
+
Output: i,
|
|
167
|
+
Description: EnvMeta.outputs[i].description
|
|
168
|
+
}))
|
|
169
|
+
)
|
|
170
|
+
console.log()
|
|
171
|
+
|
|
172
|
+
if (Object.keys(EnvMeta.caches).length > 0) {
|
|
173
|
+
console.table(
|
|
174
|
+
Object.keys(EnvMeta.caches).map(i => ({
|
|
175
|
+
'Cache ID': i,
|
|
176
|
+
Filename: EnvMeta.caches[parseInt(i)]
|
|
177
|
+
}))
|
|
178
|
+
)
|
|
179
|
+
console.log()
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Defining the stubs. Next, we will load their paths based on the package
|
|
183
|
+
// manager in use.
|
|
184
|
+
const stubs = {
|
|
185
|
+
'@actions/artifact': {
|
|
186
|
+
base: undefined as string | undefined,
|
|
187
|
+
lib: ['lib', 'artifact.js'],
|
|
188
|
+
stubs: ARTIFACT_STUBS
|
|
189
|
+
},
|
|
190
|
+
'@actions/cache': {
|
|
191
|
+
base: undefined as string | undefined,
|
|
192
|
+
lib: ['lib', 'cache.js'],
|
|
193
|
+
stubs: CACHE_STUBS
|
|
194
|
+
},
|
|
195
|
+
'@actions/core': {
|
|
196
|
+
base: undefined as string | undefined,
|
|
197
|
+
lib: ['lib', 'core.js'],
|
|
198
|
+
stubs: CORE_STUBS
|
|
199
|
+
},
|
|
200
|
+
'@actions/github': {
|
|
201
|
+
base: undefined as string | undefined,
|
|
202
|
+
lib: ['lib', 'github.js'],
|
|
203
|
+
stubs: {
|
|
204
|
+
getOctokit,
|
|
205
|
+
// The context object needs to be created **after** the dotenv file is
|
|
206
|
+
// loaded. Otherwise, the GITHUB_* environment variables will not be
|
|
207
|
+
// available to the action.
|
|
208
|
+
context: new Context()
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Starting at the target action's entrypoint, find the package.json file.
|
|
214
|
+
const dirs = path.dirname(entrypoint).split(path.sep)
|
|
215
|
+
let packageJsonPath
|
|
216
|
+
let found = false
|
|
217
|
+
|
|
218
|
+
// Move up the directory tree until we find a package.json directory.
|
|
219
|
+
while (dirs.length > 0) {
|
|
220
|
+
packageJsonPath = path.resolve(dirs.join(path.sep), 'package.json')
|
|
221
|
+
|
|
222
|
+
// Check if the current directory has a package.json file.
|
|
223
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
224
|
+
found = true
|
|
225
|
+
break
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Move up the directory tree.
|
|
229
|
+
dirs.pop()
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (!found || !packageJsonPath)
|
|
233
|
+
throw new Error(
|
|
234
|
+
'No package.json file found in the action directory or any parent directories.'
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
// If the package manager is `npm`, we can assume there is a `node_modules`
|
|
238
|
+
// directory somewhere in the project.
|
|
239
|
+
//
|
|
240
|
+
// Actions that use `pnpm` will also have a `node_modules` directory, however
|
|
241
|
+
// in testing it seems that the `node_modules/@actions/<pkg>` dependency can
|
|
242
|
+
// only be properly stubbed for CJS actions. For ESM actions, this should
|
|
243
|
+
// instead point to the pnpm cache.
|
|
244
|
+
//
|
|
245
|
+
// If the package manager is `yarn`, then we need to first check for
|
|
246
|
+
// `node_modules` (for non-PnP versions), or we can try unplugging the
|
|
247
|
+
// dependencies from the yarn cache.
|
|
248
|
+
if (
|
|
249
|
+
process.env.NODE_PACKAGE_MANAGER === 'npm' ||
|
|
250
|
+
(process.env.NODE_PACKAGE_MANAGER === 'pnpm' && actionType === 'cjs') ||
|
|
251
|
+
(process.env.NODE_PACKAGE_MANAGER === 'yarn' &&
|
|
252
|
+
fs.existsSync(path.join(actionPath, 'node_modules')))
|
|
253
|
+
) {
|
|
254
|
+
/**
|
|
255
|
+
* Get the path in the npm cache for each package.
|
|
256
|
+
* `npm ls <package> --json --long`
|
|
257
|
+
*
|
|
258
|
+
* Example Output
|
|
259
|
+
*
|
|
260
|
+
* {
|
|
261
|
+
* "path": "<workspace>/typescript-action",
|
|
262
|
+
* "_dependencies": {
|
|
263
|
+
* "@actions/core": "^1.11.1",
|
|
264
|
+
* "@actions/github": "^6.0.0"
|
|
265
|
+
* },
|
|
266
|
+
* "dependencies": {
|
|
267
|
+
* "@actions/core": {
|
|
268
|
+
* "path": "<workspace>/typescript-action/node_modules/@actions/core",
|
|
269
|
+
* },
|
|
270
|
+
* "@actions/github": {
|
|
271
|
+
* "path": "<workspace>/typescript-action/node_modules/@actions/github",
|
|
272
|
+
* }
|
|
273
|
+
* }
|
|
274
|
+
* }
|
|
275
|
+
*/
|
|
276
|
+
|
|
277
|
+
const npmList = JSON.parse(
|
|
278
|
+
execSync(
|
|
279
|
+
`npm ls ${Object.keys(stubs).join(' ')} --json --long`
|
|
280
|
+
).toString()
|
|
281
|
+
) as {
|
|
282
|
+
path: string
|
|
283
|
+
dependencies?: {
|
|
284
|
+
[key: string]: { path: string }
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (Object.keys(npmList.dependencies ?? {}).length === 0)
|
|
289
|
+
throw new Error('Something went wrong with npm list')
|
|
290
|
+
|
|
291
|
+
Object.keys(stubs).forEach(key => {
|
|
292
|
+
stubs[key as keyof typeof stubs].base = npmList.dependencies?.[key]?.path
|
|
293
|
+
})
|
|
294
|
+
} else if (
|
|
295
|
+
process.env.NODE_PACKAGE_MANAGER === 'pnpm' &&
|
|
296
|
+
actionType === 'esm'
|
|
297
|
+
) {
|
|
298
|
+
/**
|
|
299
|
+
* Get the path in the pnpm cache for each package.
|
|
300
|
+
* `pnpm list <package> --json`
|
|
301
|
+
*
|
|
302
|
+
* Example Output
|
|
303
|
+
*
|
|
304
|
+
* [
|
|
305
|
+
* {
|
|
306
|
+
* "path": "<workspace>/typescript-action",
|
|
307
|
+
* "dependencies": {
|
|
308
|
+
* "@actions/core": {
|
|
309
|
+
* "path": "<workspace>/typescript-action/node_modules/.pnpm/@actions+core@1.11.1/node_modules/@actions/core"
|
|
310
|
+
* },
|
|
311
|
+
* "@actions/github": {
|
|
312
|
+
* "path": "<workspace>/typescript-action/node_modules/.pnpm/@actions+github@6.0.0/node_modules/@actions/github"
|
|
313
|
+
* }
|
|
314
|
+
* }
|
|
315
|
+
* }
|
|
316
|
+
* ]
|
|
317
|
+
*/
|
|
318
|
+
const pnpmList = JSON.parse(
|
|
319
|
+
execSync(`pnpm list ${Object.keys(stubs).join(' ')} --json`).toString()
|
|
320
|
+
) as {
|
|
321
|
+
path: string
|
|
322
|
+
dependencies?: {
|
|
323
|
+
[key: string]: { path: string }
|
|
324
|
+
}
|
|
325
|
+
}[]
|
|
326
|
+
|
|
327
|
+
if (pnpmList.length === 0)
|
|
328
|
+
throw new Error('Something went wrong with pnpm list')
|
|
329
|
+
|
|
330
|
+
Object.keys(stubs).forEach(key => {
|
|
331
|
+
stubs[key as keyof typeof stubs].base =
|
|
332
|
+
pnpmList[0].dependencies?.[key]?.path
|
|
333
|
+
})
|
|
334
|
+
} else if (process.env.NODE_PACKAGE_MANAGER === 'yarn') {
|
|
335
|
+
// Note: The CLI commands are different across yarn versions for getting the
|
|
336
|
+
// path to a dependency.
|
|
337
|
+
|
|
338
|
+
// At this point, it's likely yarn is running in PnP mode.
|
|
339
|
+
printTitle(CoreMeta.colors.magenta, 'Yarn: Unplugging Dependencies')
|
|
340
|
+
console.log()
|
|
341
|
+
|
|
342
|
+
// For now, we need to `unplug` each dependency to get the path to the
|
|
343
|
+
// package.
|
|
344
|
+
needsReplug = true
|
|
345
|
+
|
|
346
|
+
for (const key of Object.keys(stubs)) {
|
|
347
|
+
// This may fail if the package is not a dependency for this action.
|
|
348
|
+
try {
|
|
349
|
+
const output = execSync(`yarn unplug ${key}`).toString()
|
|
350
|
+
console.log(`Unplugged: ${key}`)
|
|
351
|
+
|
|
352
|
+
// Next, get the path to the package. Unfortunately using the `--json`
|
|
353
|
+
// flag with `yarn unplug` does not output the target path, so we need
|
|
354
|
+
// to parse it from the plaintext output.
|
|
355
|
+
const packagePath = output.match(/Will unpack .* to (?<packagePath>.*)/)
|
|
356
|
+
?.groups?.packagePath
|
|
357
|
+
|
|
358
|
+
if (!packagePath) throw new Error(`Could not unplug ${key}`)
|
|
359
|
+
|
|
360
|
+
stubs[key as keyof typeof stubs].base = path.join(
|
|
361
|
+
packagePath,
|
|
362
|
+
'node_modules',
|
|
363
|
+
key
|
|
364
|
+
)
|
|
365
|
+
} catch {
|
|
366
|
+
// This is fine...
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const osEntrypoints = getOSEntrypoints(actionType)
|
|
372
|
+
|
|
373
|
+
// Stub the `@actions/toolkit` libraries and run the action. Quibble and
|
|
374
|
+
// local-action require a different approach depending on if the called action
|
|
375
|
+
// is written in ESM. The stubs should only be loaded if the corresponding
|
|
376
|
+
// package is installed.
|
|
377
|
+
if (actionType === 'esm') {
|
|
378
|
+
if (stubs['@actions/artifact'].base)
|
|
379
|
+
await quibble.default.esm(
|
|
380
|
+
path.resolve(
|
|
381
|
+
stubs['@actions/artifact'].base,
|
|
382
|
+
...stubs['@actions/artifact'].lib
|
|
383
|
+
),
|
|
384
|
+
stubs['@actions/artifact'].stubs
|
|
385
|
+
)
|
|
386
|
+
|
|
387
|
+
if (stubs['@actions/cache'].base)
|
|
388
|
+
await quibble.default.esm(
|
|
389
|
+
path.resolve(
|
|
390
|
+
stubs['@actions/cache'].base,
|
|
391
|
+
...stubs['@actions/cache'].lib
|
|
392
|
+
),
|
|
393
|
+
stubs['@actions/cache'].stubs
|
|
394
|
+
)
|
|
395
|
+
|
|
396
|
+
if (stubs['@actions/core'].base)
|
|
397
|
+
await quibble.default.esm(
|
|
398
|
+
path.resolve(
|
|
399
|
+
stubs['@actions/core'].base,
|
|
400
|
+
...stubs['@actions/core'].lib
|
|
401
|
+
),
|
|
402
|
+
stubs['@actions/core'].stubs
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
if (stubs['@actions/github'].base)
|
|
406
|
+
await quibble.default.esm(
|
|
407
|
+
path.resolve(
|
|
408
|
+
stubs['@actions/github'].base,
|
|
409
|
+
...stubs['@actions/github'].lib
|
|
410
|
+
),
|
|
411
|
+
stubs['@actions/github'].stubs
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
try {
|
|
415
|
+
if (osEntrypoints.pre) {
|
|
416
|
+
console.log('')
|
|
417
|
+
printTitle(CoreMeta.colors.red, 'Running Pre Step')
|
|
418
|
+
console.log('')
|
|
419
|
+
|
|
420
|
+
const { run: pre } = await import(osEntrypoints.pre)
|
|
421
|
+
|
|
422
|
+
// Check if the required path is a function.
|
|
423
|
+
if (typeof pre !== 'function')
|
|
424
|
+
throw new Error(
|
|
425
|
+
`Entrypoint ${options.pre} does not export a run() function`
|
|
426
|
+
)
|
|
427
|
+
|
|
428
|
+
await pre()
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
console.log('')
|
|
432
|
+
printTitle(CoreMeta.colors.green, 'Running Action')
|
|
433
|
+
console.log('')
|
|
434
|
+
|
|
435
|
+
// ESM actions need to be imported, not required.
|
|
436
|
+
const { run } = await import(osEntrypoints.main)
|
|
437
|
+
|
|
438
|
+
// Check if the required path is a function.
|
|
439
|
+
if (typeof run !== 'function')
|
|
440
|
+
throw new Error(
|
|
441
|
+
`Entrypoint ${entrypoint} does not export a run() function`
|
|
442
|
+
)
|
|
443
|
+
|
|
444
|
+
await run()
|
|
445
|
+
|
|
446
|
+
if (osEntrypoints.post) {
|
|
447
|
+
console.log('')
|
|
448
|
+
printTitle(CoreMeta.colors.red, 'Running Post Step')
|
|
449
|
+
console.log('')
|
|
450
|
+
|
|
451
|
+
const { run: post } = await import(osEntrypoints.post)
|
|
452
|
+
|
|
453
|
+
// Check if the required path is a function.
|
|
454
|
+
if (typeof post !== 'function')
|
|
455
|
+
throw new Error(
|
|
456
|
+
`Entrypoint ${options.post} does not export a run() function`
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
await post()
|
|
460
|
+
}
|
|
461
|
+
} finally {
|
|
462
|
+
if (process.env.NODE_PACKAGE_MANAGER === 'yarn' && needsReplug)
|
|
463
|
+
replug(fs, packageJsonPath, Object.keys(stubs))
|
|
464
|
+
}
|
|
465
|
+
} else {
|
|
466
|
+
if (stubs['@actions/artifact'].base)
|
|
467
|
+
quibble.default(
|
|
468
|
+
path.resolve(
|
|
469
|
+
stubs['@actions/artifact'].base,
|
|
470
|
+
...stubs['@actions/artifact'].lib
|
|
471
|
+
),
|
|
472
|
+
stubs['@actions/artifact'].stubs
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
if (stubs['@actions/cache'].base)
|
|
476
|
+
quibble.default(
|
|
477
|
+
path.resolve(
|
|
478
|
+
stubs['@actions/cache'].base,
|
|
479
|
+
...stubs['@actions/cache'].lib
|
|
480
|
+
),
|
|
481
|
+
stubs['@actions/cache'].stubs
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
if (stubs['@actions/core'].base)
|
|
485
|
+
quibble.default(
|
|
486
|
+
path.resolve(
|
|
487
|
+
stubs['@actions/core'].base,
|
|
488
|
+
...stubs['@actions/core'].lib
|
|
489
|
+
),
|
|
490
|
+
stubs['@actions/core'].stubs
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
if (stubs['@actions/github'].base)
|
|
494
|
+
quibble.default(
|
|
495
|
+
path.resolve(
|
|
496
|
+
stubs['@actions/github'].base,
|
|
497
|
+
...stubs['@actions/github'].lib
|
|
498
|
+
),
|
|
499
|
+
stubs['@actions/github'].stubs
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
try {
|
|
503
|
+
if (osEntrypoints.pre) {
|
|
504
|
+
console.log('')
|
|
505
|
+
printTitle(CoreMeta.colors.red, 'Running Pre Step')
|
|
506
|
+
console.log('')
|
|
507
|
+
|
|
508
|
+
// CJS actions need to be required, not imported.
|
|
509
|
+
const { run: pre } = require(osEntrypoints.pre)
|
|
510
|
+
|
|
511
|
+
// Check if the required path is a function.
|
|
512
|
+
if (typeof pre !== 'function')
|
|
513
|
+
throw new Error(
|
|
514
|
+
`Entrypoint ${options.pre} does not export a run() function`
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
await pre()
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
console.log('')
|
|
521
|
+
printTitle(CoreMeta.colors.green, 'Running Action')
|
|
522
|
+
console.log('')
|
|
523
|
+
|
|
524
|
+
// CJS actions need to be required, not imported.
|
|
525
|
+
const { run } = require(osEntrypoints.main)
|
|
526
|
+
|
|
527
|
+
// Check if the required path is a function.
|
|
528
|
+
if (typeof run !== 'function')
|
|
529
|
+
throw new Error(
|
|
530
|
+
`Entrypoint ${EnvMeta.entrypoint} does not export a run() function`
|
|
531
|
+
)
|
|
532
|
+
|
|
533
|
+
await run()
|
|
534
|
+
|
|
535
|
+
if (osEntrypoints.post) {
|
|
536
|
+
console.log('')
|
|
537
|
+
printTitle(CoreMeta.colors.red, 'Running Post Step')
|
|
538
|
+
console.log('')
|
|
539
|
+
|
|
540
|
+
// CJS actions need to be required, not imported.
|
|
541
|
+
const { run: post } = require(osEntrypoints.post)
|
|
542
|
+
|
|
543
|
+
// Check if the required path is a function.
|
|
544
|
+
if (typeof post !== 'function')
|
|
545
|
+
throw new Error(
|
|
546
|
+
`Entrypoint ${options.post} does not export a run() function`
|
|
547
|
+
)
|
|
548
|
+
|
|
549
|
+
await post()
|
|
550
|
+
}
|
|
551
|
+
} finally {
|
|
552
|
+
if (process.env.NODE_PACKAGE_MANAGER === 'yarn' && needsReplug)
|
|
553
|
+
replug(fs, packageJsonPath, Object.keys(stubs))
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Print the action outputs, if any.
|
|
558
|
+
console.log('')
|
|
559
|
+
printTitle(CoreMeta.colors.yellow, 'Action Outputs')
|
|
560
|
+
console.log('')
|
|
561
|
+
|
|
562
|
+
if (Object.keys(CoreMeta.outputs).length > 0)
|
|
563
|
+
console.table(
|
|
564
|
+
Object.keys(CoreMeta.outputs).map(key => ({
|
|
565
|
+
Output: key,
|
|
566
|
+
Value: CoreMeta.outputs[key]
|
|
567
|
+
}))
|
|
568
|
+
)
|
|
569
|
+
else console.log('No outputs were set!')
|
|
570
|
+
console.log('')
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* "Re-plugs" yarn dependencies.
|
|
575
|
+
*
|
|
576
|
+
* For yarn PnP support, we need to unplug any stubbed dependencies. This should
|
|
577
|
+
* only be temporary, so as a final step we need to "re-plug" them.
|
|
578
|
+
*
|
|
579
|
+
* In this case, we're taking the easy way and just updating the
|
|
580
|
+
* `dependenciesMeta` property in `package.json`.
|
|
581
|
+
*/
|
|
582
|
+
export function replug(
|
|
583
|
+
fs: typeof import('fs'),
|
|
584
|
+
packageJsonPath: string,
|
|
585
|
+
stubs: string[]
|
|
586
|
+
): void {
|
|
587
|
+
console.log()
|
|
588
|
+
printTitle(CoreMeta.colors.magenta, 'Yarn: Re-Plugging Dependencies')
|
|
589
|
+
console.log()
|
|
590
|
+
|
|
591
|
+
// For each of the stubs, remove the "unplugged" property from the
|
|
592
|
+
// `dependenciesMeta` property in package.json.
|
|
593
|
+
const packageJson = JSON.parse(
|
|
594
|
+
fs.readFileSync(packageJsonPath, { encoding: 'utf8', flag: 'r' })
|
|
595
|
+
) as {
|
|
596
|
+
dependenciesMeta: {
|
|
597
|
+
[key: string]: {
|
|
598
|
+
unplugged?: boolean
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Remove the unplugged property from the dependenciesMeta object.
|
|
604
|
+
for (const stub of stubs)
|
|
605
|
+
for (const key of Object.keys(packageJson.dependenciesMeta ?? {}))
|
|
606
|
+
if (key.startsWith(stub)) {
|
|
607
|
+
packageJson.dependenciesMeta[key].unplugged = false
|
|
608
|
+
console.log(`Replugged: ${stub}`)
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Save the file.
|
|
612
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2), {
|
|
613
|
+
encoding: 'utf8',
|
|
614
|
+
flag: 'w'
|
|
615
|
+
})
|
|
616
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import type { Command } from 'commander'
|
|
3
|
+
import { makeProgram } from './command.js'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Runs the Program
|
|
7
|
+
*/
|
|
8
|
+
export async function run(): Promise<void> {
|
|
9
|
+
const chalk = (await import('chalk')).default
|
|
10
|
+
const { textSync } = (await import('figlet')).default
|
|
11
|
+
|
|
12
|
+
// Print the header
|
|
13
|
+
console.log(chalk.blue(textSync('Action Debugger')))
|
|
14
|
+
|
|
15
|
+
// Run the program
|
|
16
|
+
const program: Command = await makeProgram()
|
|
17
|
+
program.parse()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/* istanbul ignore next */
|
|
21
|
+
run()
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Last Reviewed Commit: https://github.com/actions/toolkit/blob/ee91adfbc4f4d1470e176a8d568c0cbdabaf98e0/packages/artifact/src/artifact.ts
|
|
3
|
+
* Last Reviewed Date: 2026-01-16
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
type ArtifactClient,
|
|
8
|
+
DefaultArtifactClient
|
|
9
|
+
} from './internal/client.js'
|
|
10
|
+
|
|
11
|
+
const client: ArtifactClient = new DefaultArtifactClient()
|
|
12
|
+
export default client
|
|
13
|
+
|
|
14
|
+
export const ARTIFACT_STUBS = {
|
|
15
|
+
DefaultArtifactClient,
|
|
16
|
+
client
|
|
17
|
+
}
|