@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.
Files changed (223) hide show
  1. package/.checkov.yml +3 -0
  2. package/.env.example +379 -0
  3. package/.github/codeql/codeql-config.yml +7 -0
  4. package/.github/copilot-instructions.md +79 -0
  5. package/.github/dependabot.yml +32 -0
  6. package/.github/workflows/codeql-analysis.yml +53 -0
  7. package/.github/workflows/continuous-delivery.yml +93 -0
  8. package/.github/workflows/continuous-integration.yml +382 -0
  9. package/.github/workflows/linter.yml +47 -0
  10. package/.github/workflows/release.yaml +99 -0
  11. package/.github/workflows/version-check.yml +44 -0
  12. package/.grype.yml +151 -0
  13. package/.markdown-lint.yml +7 -0
  14. package/.mega-linter.yml +188 -0
  15. package/.node-version +1 -0
  16. package/.prettierignore +4 -0
  17. package/.prettierrc.yml +14 -0
  18. package/.vscode/launch.json +15 -0
  19. package/.vscode/mcp.json +9 -0
  20. package/.vscode/settings.json +15 -0
  21. package/.vscode/tasks.json +51 -0
  22. package/.yaml-lint.yml +10 -0
  23. package/CHANGELOG.md +75 -0
  24. package/CODEOWNERS +3 -0
  25. package/CODE_OF_CONDUCT.md +74 -0
  26. package/CONTRIBUTING.md +140 -0
  27. package/LICENSE +21 -0
  28. package/README.md +285 -2
  29. package/SECURITY.md +42 -0
  30. package/SUPPORT.md +19 -0
  31. package/__fixtures__/@actions/core.ts +14 -0
  32. package/__fixtures__/@actions/exec.ts +9 -0
  33. package/__fixtures__/@actions/github.ts +3 -0
  34. package/__fixtures__/@actions/http-client.ts +9 -0
  35. package/__fixtures__/@actions/io.ts +9 -0
  36. package/__fixtures__/@octokit/rest.ts +18 -0
  37. package/__fixtures__/crypto.ts +7 -0
  38. package/__fixtures__/fs.ts +27 -0
  39. package/__fixtures__/javascript/no-export/.env.fixture +2 -0
  40. package/__fixtures__/javascript/no-export/action.yml +16 -0
  41. package/__fixtures__/javascript/no-export/node_modules/.gitkeep +0 -0
  42. package/__fixtures__/javascript/no-export/package.json +12 -0
  43. package/__fixtures__/javascript/no-export/src/index.js +0 -0
  44. package/__fixtures__/javascript/no-export/src/main.js +0 -0
  45. package/__fixtures__/javascript/no-import/.env.fixture +2 -0
  46. package/__fixtures__/javascript/no-import/action.yml +16 -0
  47. package/__fixtures__/javascript/no-import/node_modules/.gitkeep +0 -0
  48. package/__fixtures__/javascript/no-import/package.json +12 -0
  49. package/__fixtures__/javascript/no-import/src/index.js +3 -0
  50. package/__fixtures__/javascript/no-import/src/main.js +7 -0
  51. package/__fixtures__/javascript/success/.env.fixture +2 -0
  52. package/__fixtures__/javascript/success/action.yml +16 -0
  53. package/__fixtures__/javascript/success/node_modules/.gitkeep +0 -0
  54. package/__fixtures__/javascript/success/package.json +12 -0
  55. package/__fixtures__/javascript/success/post/index.js +3 -0
  56. package/__fixtures__/javascript/success/post/main.js +13 -0
  57. package/__fixtures__/javascript/success/pre/index.js +3 -0
  58. package/__fixtures__/javascript/success/pre/main.js +13 -0
  59. package/__fixtures__/javascript/success/src/index.js +3 -0
  60. package/__fixtures__/javascript/success/src/main.js +13 -0
  61. package/__fixtures__/javascript-esm/no-import/.env.fixture +2 -0
  62. package/__fixtures__/javascript-esm/no-import/action.yml +16 -0
  63. package/__fixtures__/javascript-esm/no-import/node_modules/.gitkeep +0 -0
  64. package/__fixtures__/javascript-esm/no-import/package.json +13 -0
  65. package/__fixtures__/javascript-esm/no-import/src/index.js +3 -0
  66. package/__fixtures__/javascript-esm/no-import/src/main.js +7 -0
  67. package/__fixtures__/javascript-esm/success/.env.fixture +2 -0
  68. package/__fixtures__/javascript-esm/success/action.yml +16 -0
  69. package/__fixtures__/javascript-esm/success/node_modules/.gitkeep +0 -0
  70. package/__fixtures__/javascript-esm/success/package.json +13 -0
  71. package/__fixtures__/javascript-esm/success/post/index.js +3 -0
  72. package/__fixtures__/javascript-esm/success/post/main.js +13 -0
  73. package/__fixtures__/javascript-esm/success/pre/index.js +3 -0
  74. package/__fixtures__/javascript-esm/success/pre/main.js +13 -0
  75. package/__fixtures__/javascript-esm/success/src/index.js +3 -0
  76. package/__fixtures__/javascript-esm/success/src/main.js +13 -0
  77. package/__fixtures__/path.ts +7 -0
  78. package/__fixtures__/payloads/issue_opened.json +33 -0
  79. package/__fixtures__/stream/promises.ts +3 -0
  80. package/__fixtures__/tsconfig-paths.ts +4 -0
  81. package/__fixtures__/typescript/no-import/.env.fixture +2 -0
  82. package/__fixtures__/typescript/no-import/action.yml +16 -0
  83. package/__fixtures__/typescript/no-import/node_modules/.gitkeep +0 -0
  84. package/__fixtures__/typescript/no-import/package.json +15 -0
  85. package/__fixtures__/typescript/no-import/src/index.ts +3 -0
  86. package/__fixtures__/typescript/no-import/src/main.ts +3 -0
  87. package/__fixtures__/typescript/no-import/tsconfig.json +20 -0
  88. package/__fixtures__/typescript/success/.env.fixture +2 -0
  89. package/__fixtures__/typescript/success/action.yml +16 -0
  90. package/__fixtures__/typescript/success/node_modules/.gitkeep +0 -0
  91. package/__fixtures__/typescript/success/package.json +15 -0
  92. package/__fixtures__/typescript/success/post/index.ts +3 -0
  93. package/__fixtures__/typescript/success/post/main.ts +9 -0
  94. package/__fixtures__/typescript/success/pre/index.ts +3 -0
  95. package/__fixtures__/typescript/success/pre/main.ts +9 -0
  96. package/__fixtures__/typescript/success/src/index.ts +3 -0
  97. package/__fixtures__/typescript/success/src/main.ts +9 -0
  98. package/__fixtures__/typescript/success/tsconfig.json +20 -0
  99. package/__fixtures__/typescript/success-yaml/.env.fixture +2 -0
  100. package/__fixtures__/typescript/success-yaml/action.yaml +16 -0
  101. package/__fixtures__/typescript/success-yaml/node_modules/.gitkeep +0 -0
  102. package/__fixtures__/typescript/success-yaml/package.json +15 -0
  103. package/__fixtures__/typescript/success-yaml/post/index.ts +3 -0
  104. package/__fixtures__/typescript/success-yaml/post/main.ts +9 -0
  105. package/__fixtures__/typescript/success-yaml/pre/index.ts +3 -0
  106. package/__fixtures__/typescript/success-yaml/pre/main.ts +9 -0
  107. package/__fixtures__/typescript/success-yaml/src/index.ts +3 -0
  108. package/__fixtures__/typescript/success-yaml/src/main.ts +9 -0
  109. package/__fixtures__/typescript/success-yaml/tsconfig.json +20 -0
  110. package/__fixtures__/typescript-esm/no-export/.env.fixture +2 -0
  111. package/__fixtures__/typescript-esm/no-export/action.yml +17 -0
  112. package/__fixtures__/typescript-esm/no-export/node_modules/.gitkeep +0 -0
  113. package/__fixtures__/typescript-esm/no-export/package.json +17 -0
  114. package/__fixtures__/typescript-esm/no-export/src/index.ts +0 -0
  115. package/__fixtures__/typescript-esm/no-export/src/main.ts +0 -0
  116. package/__fixtures__/typescript-esm/no-export/tsconfig.json +25 -0
  117. package/__fixtures__/typescript-esm/no-import/.env.fixture +2 -0
  118. package/__fixtures__/typescript-esm/no-import/action.yml +17 -0
  119. package/__fixtures__/typescript-esm/no-import/node_modules/.gitkeep +0 -0
  120. package/__fixtures__/typescript-esm/no-import/package.json +17 -0
  121. package/__fixtures__/typescript-esm/no-import/src/index.ts +3 -0
  122. package/__fixtures__/typescript-esm/no-import/src/main.ts +3 -0
  123. package/__fixtures__/typescript-esm/no-import/tsconfig.json +25 -0
  124. package/__fixtures__/typescript-esm/success/.env.fixture +2 -0
  125. package/__fixtures__/typescript-esm/success/action.yml +17 -0
  126. package/__fixtures__/typescript-esm/success/node_modules/.gitkeep +0 -0
  127. package/__fixtures__/typescript-esm/success/package.json +17 -0
  128. package/__fixtures__/typescript-esm/success/post/index.ts +3 -0
  129. package/__fixtures__/typescript-esm/success/post/main.ts +9 -0
  130. package/__fixtures__/typescript-esm/success/pre/index.ts +3 -0
  131. package/__fixtures__/typescript-esm/success/pre/main.ts +9 -0
  132. package/__fixtures__/typescript-esm/success/src/index.ts +3 -0
  133. package/__fixtures__/typescript-esm/success/src/main.ts +9 -0
  134. package/__fixtures__/typescript-esm/success/tsconfig.json +25 -0
  135. package/__fixtures__/typescript-esm/tsconfig-comments/.env.fixture +2 -0
  136. package/__fixtures__/typescript-esm/tsconfig-comments/action.yml +17 -0
  137. package/__fixtures__/typescript-esm/tsconfig-comments/node_modules/.gitkeep +0 -0
  138. package/__fixtures__/typescript-esm/tsconfig-comments/package.json +17 -0
  139. package/__fixtures__/typescript-esm/tsconfig-comments/src/index.ts +3 -0
  140. package/__fixtures__/typescript-esm/tsconfig-comments/src/main.ts +9 -0
  141. package/__fixtures__/typescript-esm/tsconfig-comments/tsconfig.json +21 -0
  142. package/__tests__/command.test.ts +224 -0
  143. package/__tests__/stubs/artifact/internal/client.test.ts +340 -0
  144. package/__tests__/stubs/artifact/internal/delete/delete-artifact.test.ts +152 -0
  145. package/__tests__/stubs/artifact/internal/download/download-artifact.test.ts +119 -0
  146. package/__tests__/stubs/artifact/internal/find/get-artifact.test.ts +237 -0
  147. package/__tests__/stubs/artifact/internal/find/list-artifacts.test.ts +218 -0
  148. package/__tests__/stubs/artifact/internal/find/retry-options.test.ts +54 -0
  149. package/__tests__/stubs/artifact/internal/shared/config.test.ts +91 -0
  150. package/__tests__/stubs/artifact/internal/shared/errors.test.ts +38 -0
  151. package/__tests__/stubs/artifact/internal/shared/user-agent.test.ts +22 -0
  152. package/__tests__/stubs/artifact/internal/upload/path-and-artifact-name-validation.test.ts +53 -0
  153. package/__tests__/stubs/artifact/internal/upload/upload-artifact.test.ts +126 -0
  154. package/__tests__/stubs/artifact/internal/upload/upload-zip-specification.test.ts +49 -0
  155. package/__tests__/stubs/cache/cache.test.ts +357 -0
  156. package/__tests__/stubs/cache/errors.test.ts +55 -0
  157. package/__tests__/stubs/cache/internal/cacheUtils.test.ts +109 -0
  158. package/__tests__/stubs/cache/internal/constants.test.ts +81 -0
  159. package/__tests__/stubs/cache/internal/tar.test.ts +129 -0
  160. package/__tests__/stubs/core/core.test.ts +760 -0
  161. package/__tests__/stubs/core/path-utils.test.ts +45 -0
  162. package/__tests__/stubs/core/platform.test.ts +89 -0
  163. package/__tests__/stubs/core/summary.test.ts +455 -0
  164. package/__tests__/stubs/env.test.ts +72 -0
  165. package/__tests__/stubs/github/context.test.ts +73 -0
  166. package/__tests__/stubs/github/github.test.ts +15 -0
  167. package/__tests__/stubs/github/internal/utils.test.ts +98 -0
  168. package/__tests__/stubs/github/utils.test.ts +16 -0
  169. package/__tests__/utils/config.test.ts +78 -0
  170. package/__tests__/utils/output.test.ts +32 -0
  171. package/__tests__/utils/package.test.ts +33 -0
  172. package/badges/coverage.svg +1 -0
  173. package/bin/local-action.js +121 -0
  174. package/docs/create-a-job-summary.md +32 -0
  175. package/docs/debugging-in-vscode.md +27 -0
  176. package/docs/img/job-summary.png +0 -0
  177. package/docs/supported-functionality.md +126 -0
  178. package/eslint.config.mjs +74 -0
  179. package/jest.config.ts +41 -0
  180. package/package.json +93 -4
  181. package/src/command.ts +171 -0
  182. package/src/commands/run.ts +616 -0
  183. package/src/index.ts +21 -0
  184. package/src/stubs/artifact/artifact.ts +17 -0
  185. package/src/stubs/artifact/internal/client.ts +400 -0
  186. package/src/stubs/artifact/internal/delete/delete-artifact.ts +126 -0
  187. package/src/stubs/artifact/internal/download/download-artifact.ts +309 -0
  188. package/src/stubs/artifact/internal/find/get-artifact.ts +135 -0
  189. package/src/stubs/artifact/internal/find/list-artifacts.ts +188 -0
  190. package/src/stubs/artifact/internal/find/retry-options.ts +57 -0
  191. package/src/stubs/artifact/internal/shared/config.ts +64 -0
  192. package/src/stubs/artifact/internal/shared/errors.ts +53 -0
  193. package/src/stubs/artifact/internal/shared/interfaces.ts +195 -0
  194. package/src/stubs/artifact/internal/shared/user-agent.ts +13 -0
  195. package/src/stubs/artifact/internal/upload/path-and-artifact-name-validation.ts +92 -0
  196. package/src/stubs/artifact/internal/upload/upload-artifact.ts +127 -0
  197. package/src/stubs/artifact/internal/upload/upload-zip-specification.ts +108 -0
  198. package/src/stubs/artifact/internal/upload/zip.ts +122 -0
  199. package/src/stubs/cache/cache.ts +334 -0
  200. package/src/stubs/cache/errors.ts +31 -0
  201. package/src/stubs/cache/interfaces.ts +4 -0
  202. package/src/stubs/cache/internal/cacheUtils.ts +207 -0
  203. package/src/stubs/cache/internal/constants.ts +45 -0
  204. package/src/stubs/cache/internal/tar.ts +374 -0
  205. package/src/stubs/cache/options.ts +91 -0
  206. package/src/stubs/core/core.ts +743 -0
  207. package/src/stubs/core/path-utils.ts +39 -0
  208. package/src/stubs/core/platform.ts +132 -0
  209. package/src/stubs/core/summary.ts +399 -0
  210. package/src/stubs/env.ts +40 -0
  211. package/src/stubs/github/context.ts +94 -0
  212. package/src/stubs/github/github.ts +29 -0
  213. package/src/stubs/github/interfaces.ts +52 -0
  214. package/src/stubs/github/internal/utils.ts +83 -0
  215. package/src/stubs/github/utils.ts +52 -0
  216. package/src/types/quibble.d.ts +5 -0
  217. package/src/types.ts +116 -0
  218. package/src/utils/config.ts +47 -0
  219. package/src/utils/output.ts +20 -0
  220. package/src/utils/package.ts +38 -0
  221. package/tsconfig.base.json +29 -0
  222. package/tsconfig.eslint.json +22 -0
  223. package/tsconfig.json +18 -0
@@ -0,0 +1,743 @@
1
+ /**
2
+ * Last Reviewed Commit: 6876e2a664ec02908178087905b9155e9892a437
3
+ * Last Reviewed Date: 2026-01-16
4
+ *
5
+ * @remarks
6
+ *
7
+ * - Across the board, the `issueCommand` and `issueFileCommand` calls were
8
+ * removed for easier implementation and testing.
9
+ */
10
+
11
+ import path from 'path'
12
+ import type { CoreMetadata } from '../../types.js'
13
+ import { EnvMeta } from '../env.js'
14
+ import { toPlatformPath, toPosixPath, toWin32Path } from './path-utils.js'
15
+ import * as platform from './platform.js'
16
+ import { Summary } from './summary.js'
17
+
18
+ export const CORE_STUBS = {
19
+ addPath,
20
+ debug,
21
+ endGroup,
22
+ error,
23
+ exportVariable,
24
+ getBooleanInput,
25
+ getIDToken,
26
+ getInput,
27
+ getMultilineInput,
28
+ getState,
29
+ group,
30
+ info,
31
+ isDebug,
32
+ notice,
33
+ platform,
34
+ saveState,
35
+ setCommandEcho,
36
+ setFailed,
37
+ setOutput,
38
+ setSecret,
39
+ startGroup,
40
+ summary: new Summary(),
41
+ toPlatformPath,
42
+ toPosixPath,
43
+ toWin32Path,
44
+ warning
45
+ }
46
+
47
+ /**
48
+ * Metadata for `@actions/core`
49
+ */
50
+ export const CoreMeta: CoreMetadata = {
51
+ echo: false,
52
+ exitCode: 0,
53
+ exitMessage: '',
54
+ outputs: {},
55
+ secrets: [],
56
+ state: {},
57
+ stepDebug: process.env.ACTIONS_STEP_DEBUG === 'true',
58
+ stepSummaryPath:
59
+ /* istanbul ignore next*/ process.env.GITHUB_STEP_SUMMARY ?? '',
60
+ colors: {
61
+ cyan: (msg: string) => console.log(msg),
62
+ blue: (msg: string) => console.log(msg),
63
+ gray: (msg: string) => console.log(msg),
64
+ green: (msg: string) => console.log(msg),
65
+ magenta: (msg: string) => console.log(msg),
66
+ red: (msg: string) => console.log(msg),
67
+ white: (msg: string) => console.log(msg),
68
+ yellow: (msg: string) => console.log(msg)
69
+ }
70
+ }
71
+
72
+ /**
73
+ * Resets the core metadata
74
+ *
75
+ * @returns void
76
+ */
77
+ export function ResetCoreMetadata(): void {
78
+ CoreMeta.echo = false
79
+ CoreMeta.exitCode = 0
80
+ CoreMeta.exitMessage = ''
81
+ CoreMeta.outputs = {}
82
+ CoreMeta.secrets = []
83
+ CoreMeta.state = {}
84
+ CoreMeta.stepDebug = process.env.ACTIONS_STEP_DEBUG === 'true'
85
+ CoreMeta.stepSummaryPath = process.env.GITHUB_STEP_SUMMARY ?? ''
86
+ }
87
+
88
+ /**
89
+ * Optional properties that can be sent with annotation commands (notice, error,
90
+ * and warning).
91
+ */
92
+ export type AnnotationProperties = {
93
+ /** A title for the annotation. */
94
+ title?: string
95
+
96
+ /** The path of the file for which the annotation should be created. */
97
+ file?: string
98
+
99
+ /** The start line for the annotation. */
100
+ startLine?: number
101
+
102
+ /**
103
+ * The end line for the annotation. Defaults to `startLine` when `startLine`
104
+ * is provided.
105
+ */
106
+ endLine?: number
107
+
108
+ /**
109
+ * The start column for the annotation. Cannot be sent when `startLine` and
110
+ * `endLine` are different values.
111
+ */
112
+ startColumn?: number
113
+
114
+ /**
115
+ * The end column for the annotation. Cannot be sent when `startLine` and
116
+ * `endLine` are different values. Defaults to `startColumn` when
117
+ * `startColumn` is provided.
118
+ */
119
+ endColumn?: number
120
+ }
121
+
122
+ /**
123
+ * Options for getInput.
124
+ */
125
+ export type InputOptions = {
126
+ /**
127
+ * Optional. Whether the input is required. If required and not present,
128
+ * will throw. Defaults to false.
129
+ */
130
+ required?: boolean
131
+
132
+ /**
133
+ * Optional. Whether leading/trailing whitespace will be trimmed for the
134
+ * input. Defaults to true.
135
+ */
136
+ trimWhitespace?: boolean
137
+ }
138
+
139
+ /**
140
+ * Prepends to the PATH
141
+ *
142
+ * @remarks
143
+ *
144
+ * - Use environment metadata to track updated PATH
145
+ *
146
+ * @param inputPath The path to prepend to the PATH
147
+ * @returns void
148
+ */
149
+ export function addPath(inputPath: string): void {
150
+ EnvMeta.path = `${inputPath}${path.delimiter}${process.env.PATH}`
151
+ process.env.PATH = EnvMeta.path
152
+ }
153
+
154
+ //-----------------------------------------------------------------------
155
+ // Variables
156
+ //-----------------------------------------------------------------------
157
+
158
+ /**
159
+ * Saves an environment variable
160
+ *
161
+ * @remarks
162
+ *
163
+ * - Saves variables to the environment metadata.
164
+ *
165
+ * @param name The name of the environment variable
166
+ * @param value The value of the environment variable
167
+ * @returns void
168
+ */
169
+ export function exportVariable(
170
+ name: string,
171
+ value: string | undefined | null | object
172
+ ): void {
173
+ // Convert the value to a string
174
+ value =
175
+ value === undefined || value === null
176
+ ? ''
177
+ : typeof value === 'string' || value instanceof String
178
+ ? value.toString()
179
+ : JSON.stringify(value)
180
+
181
+ EnvMeta.env[name] = value
182
+ process.env[name] = value
183
+ }
184
+
185
+ /**
186
+ * Register a secret to mask it in logs
187
+ *
188
+ * @remarks
189
+ *
190
+ * - Adds secrets to core metadata.
191
+ *
192
+ * @param secret The value to register
193
+ * @returns void
194
+ */
195
+ export function setSecret(secret: string): void {
196
+ CoreMeta.secrets.push(secret)
197
+ }
198
+
199
+ /**
200
+ * Gets the action input from the environment variables
201
+ *
202
+ * @remarks
203
+ *
204
+ * - Adds support for lowercase environment variables.
205
+ * - Checks default values from the action.yml file.
206
+ *
207
+ * @param name The name of the input
208
+ * @param options The options for the input
209
+ * @returns The value of the input
210
+ */
211
+ export function getInput(name: string, options?: InputOptions): string {
212
+ // Get input by name, or an empty string if not found
213
+ let input: string =
214
+ process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] ||
215
+ process.env[`INPUT_${name.replace(/ /g, '_')}`] ||
216
+ ''
217
+
218
+ // If the input is not present in the environment variables, it has not been
219
+ // set. In that case, check the default value.
220
+ if (input === '' && EnvMeta.inputs[name]?.default !== undefined)
221
+ input = EnvMeta.inputs[name].default.toString()
222
+
223
+ // Throw an error if the input is required and not supplied
224
+ if (options && options.required === true && input === '')
225
+ throw new Error(`Input required and not supplied: ${name}`)
226
+
227
+ // Trim whitespace, if specified
228
+ if (options && options.trimWhitespace === true) input = input.trim()
229
+
230
+ return input
231
+ }
232
+
233
+ /**
234
+ * Gets multiline inputs from environment variables
235
+ *
236
+ * @remarks
237
+ *
238
+ * - Adds support for lowercase environment variables.
239
+ * - Checks default values from the action.yml file.
240
+ *
241
+ * @param name The name of the input
242
+ * @param options The options for the input
243
+ * @returns The value of the input
244
+ */
245
+ export function getMultilineInput(
246
+ name: string,
247
+ options?: InputOptions
248
+ ): string[] {
249
+ // Get input by name, split by newline, and filter out empty strings
250
+ let input: string[] = (
251
+ process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] ||
252
+ process.env[`INPUT_${name.replace(/ /g, '_')}`] ||
253
+ ''
254
+ )
255
+ .split('\n')
256
+ .filter(x => x !== '')
257
+
258
+ // If the input is not present in the environment variables, it has not been
259
+ // set. In that case, check the default value.
260
+ if (input.length === 0 && EnvMeta.inputs[name]?.default !== undefined)
261
+ input = EnvMeta.inputs[name].default
262
+ .toString()
263
+ .split('\n')
264
+ .filter(x => x !== '')
265
+
266
+ // Throw an error if the input is required and not supplied
267
+ if (options && options.required === true && input.length === 0)
268
+ throw new Error(`Input required and not supplied: ${name}`)
269
+
270
+ // Trim whitespace, if specified
271
+ if (options && options.trimWhitespace === true)
272
+ return input.map(x => x.trim())
273
+
274
+ return input
275
+ }
276
+
277
+ /**
278
+ * Gets boolean inputs from environment variables
279
+ *
280
+ * @remarks
281
+ *
282
+ * - Adds support for lowercase environment variables.
283
+ * - Checks default values from the action.yml file.
284
+ *
285
+ * @param name The name of the input
286
+ * @param options The options for the input
287
+ * @returns The value of the input
288
+ */
289
+ export function getBooleanInput(name: string, options?: InputOptions): boolean {
290
+ // This is effectively a copy of the actual `getInput` function, instead of
291
+ // using proxyquire's `callThru()` option.
292
+
293
+ // Get input by name, or an empty string if not found
294
+ let input: string = (
295
+ process.env[`INPUT_${name.replace(/ /g, '_').toUpperCase()}`] ||
296
+ process.env[`INPUT_${name.replace(/ /g, '_')}`] ||
297
+ ''
298
+ ).trim()
299
+
300
+ // If the input is not present in the environment variables, it has not been
301
+ // set. In that case, check the default value.
302
+ if (input === '' && EnvMeta.inputs[name]?.default !== undefined) {
303
+ // we call .toString in case its a boolean
304
+ input = EnvMeta.inputs[name].default.toString().trim()
305
+ }
306
+
307
+ // Throw an error if the input is required and not supplied
308
+ if (input === '')
309
+ if (options && options.required === true) {
310
+ throw new Error(`Input required and not supplied: ${name}`)
311
+ } else {
312
+ // here is where we would ideally return either `false` or `undefined` but we'll need upstream changes
313
+ }
314
+
315
+ if (['true', 'True', 'TRUE'].includes(input)) return true
316
+ if (['false', 'False', 'FALSE'].includes(input)) return false
317
+
318
+ // Throw an error if the input is not a boolean
319
+ throw new TypeError(
320
+ `Input does not meet YAML 1.2 "Core Schema" specification: ${name}\n` +
321
+ `Support boolean input list: \`true | True | TRUE | false | False | FALSE\``
322
+ )
323
+ }
324
+
325
+ /**
326
+ * Saves outputs and logs to the console
327
+ *
328
+ * @remarks
329
+ *
330
+ * - Saves outputs to the core metadata.
331
+ * - Adds extra debugging output.
332
+ *
333
+ * @param name The name of the output
334
+ * @param value The value of the output
335
+ * @returns void
336
+ */
337
+ export function setOutput(name: string, value: any): void {
338
+ // Ideally the value is a string, but if not, we must convert it.
339
+ const convertedValue =
340
+ typeof value === 'string'
341
+ ? value
342
+ : value === undefined || value === null
343
+ ? ''
344
+ : typeof value === 'object' || value instanceof Object
345
+ ? JSON.stringify(value)
346
+ : value.toString()
347
+
348
+ // If an output contains a secret, log the following and skip adding to the
349
+ // core metadata.
350
+ //
351
+ // "Skip output {output.Key} since it may contain secret."
352
+ //
353
+ // This is done by GitHub Actions itself, not by @actions/core...
354
+ // https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs#overview
355
+ if (CoreMeta.secrets.some(secret => convertedValue.includes(secret)))
356
+ return warning(`Skip output ${name} since it may contain secret.`)
357
+
358
+ // Save the output to the core metadata
359
+ CoreMeta.outputs[name] = convertedValue
360
+
361
+ // This command is deprecated...it is being used here so there's meaningful
362
+ // log output for debugging purposes.
363
+ CoreMeta.colors.cyan(`::set-output name=${name}::${convertedValue}`)
364
+ }
365
+
366
+ /**
367
+ * Enables or disables the echoing of commands into stdout.
368
+ *
369
+ * @remarks
370
+ *
371
+ * - Currently this does nothing.
372
+ *
373
+ * @param enabled Whether to enable command echoing
374
+ * @returns void
375
+ */
376
+ export function setCommandEcho(enabled: boolean): void {
377
+ CoreMeta.echo = enabled
378
+ }
379
+
380
+ //-----------------------------------------------------------------------
381
+ // Results
382
+ //-----------------------------------------------------------------------
383
+
384
+ /**
385
+ * Set the action status to failed
386
+ *
387
+ * @remarks
388
+ *
389
+ * - Sets exit code and message in core metadata.
390
+ * - Does not set a failure exit code for the process.
391
+ *
392
+ * @param message The message to log
393
+ * @returns void
394
+ */
395
+ export function setFailed(message: string | Error): void {
396
+ CoreMeta.exitCode = 1
397
+ CoreMeta.exitMessage = message.toString()
398
+
399
+ error(message.toString())
400
+ }
401
+
402
+ //-----------------------------------------------------------------------
403
+ // Logging Commands
404
+ //-----------------------------------------------------------------------
405
+
406
+ /**
407
+ * Logs a message with optional annotations
408
+ *
409
+ * This is used internally by the other logging functions. It doesn't need to be
410
+ * called directly.
411
+ *
412
+ * @remarks
413
+ *
414
+ * - This is specific to the local-action tool and is used to centralize log
415
+ * formatting and styling.
416
+ *
417
+ * @param type The type of log message
418
+ * @param message The message to log
419
+ * @param properties The annotation properties
420
+ * @returns void
421
+ */
422
+ export function log(
423
+ type: string,
424
+ message?: string,
425
+ properties: AnnotationProperties = {
426
+ title: undefined,
427
+ file: undefined,
428
+ startLine: undefined,
429
+ endLine: undefined,
430
+ startColumn: undefined,
431
+ endColumn: undefined
432
+ }
433
+ ): void {
434
+ const params: string[] = []
435
+
436
+ const color =
437
+ {
438
+ debug: CoreMeta.colors.gray,
439
+ error: CoreMeta.colors.red,
440
+ warning: CoreMeta.colors.yellow,
441
+ notice: CoreMeta.colors.magenta,
442
+ info: CoreMeta.colors.white,
443
+ group: CoreMeta.colors.blue,
444
+ endgroup: CoreMeta.colors.blue
445
+ }[type] ?? CoreMeta.colors.gray
446
+
447
+ // Default endLine to startLine if not provided
448
+ if (properties.startLine && !properties.endLine)
449
+ properties.endLine = properties.startLine
450
+
451
+ // Default endColumn to startColumn if not provided
452
+ if (properties.startColumn && !properties.endColumn)
453
+ properties.endColumn = properties.startColumn
454
+
455
+ // Throw an error if startLine and endLine are different and startColumn or
456
+ // endColumn are set
457
+ if (
458
+ properties.startLine &&
459
+ properties.endLine &&
460
+ properties.startLine !== properties.endLine &&
461
+ (properties.startColumn || properties.endColumn)
462
+ )
463
+ throw new Error(
464
+ 'Error: Annotations spanning multiple lines must not include startColumn or endColumn'
465
+ )
466
+
467
+ if (properties.title) params.push(`title=${properties.title}`)
468
+ if (properties.file) params.push(`file=${properties.file}`)
469
+ if (properties.startLine) params.push(`line=${properties.startLine}`)
470
+ if (properties.endLine) params.push(`endLine=${properties.endLine}`)
471
+ if (properties.startColumn) params.push(`col=${properties.startColumn}`)
472
+ if (properties.endColumn) params.push(`endColumn=${properties.endColumn}`)
473
+
474
+ if (message === undefined) return color(`::${type}::`)
475
+
476
+ // Check for any secrets and redact them
477
+ for (const secret of CoreMeta.secrets)
478
+ if (message?.includes(secret)) message = message.replaceAll(secret, '****')
479
+
480
+ if (params.length > 0) color(`::${type} ${params.join(',')}::${message}`)
481
+ else color(`::${type}::${message}`)
482
+ }
483
+
484
+ /**
485
+ * Returns true if debugging is enabled
486
+ *
487
+ * @remarks
488
+ *
489
+ * - Gets status from the core metadata.
490
+ *
491
+ * @returns Whether debugging is enabled
492
+ */
493
+ export function isDebug(): boolean {
494
+ return CoreMeta.stepDebug
495
+ }
496
+
497
+ /**
498
+ * Logs a debug message to the console
499
+ *
500
+ * E.g. `::debug::{message}`
501
+ *
502
+ * @remarks
503
+ *
504
+ * - Uses custom logging utility function.
505
+ *
506
+ * @param message The message to log
507
+ * @returns void
508
+ */
509
+ export function debug(message: string): void {
510
+ // Only log debug messages if the `stepDebug` flag is set
511
+ if (!CoreMeta.stepDebug) return
512
+
513
+ log('debug', message)
514
+ }
515
+
516
+ /**
517
+ * Logs an error message to the console
518
+ *
519
+ * E.g. `::error file={name},line={line},endLine={endLine},title={title}::{message}`
520
+ *
521
+ * @remarks
522
+ *
523
+ * - Uses custom logging utility function.
524
+ *
525
+ * @param message The message to log
526
+ * @param properties The annotation properties
527
+ * @returns void
528
+ */
529
+ export function error(
530
+ message: string | Error,
531
+ properties: AnnotationProperties = {
532
+ title: undefined,
533
+ file: undefined,
534
+ startLine: undefined,
535
+ endLine: undefined,
536
+ startColumn: undefined,
537
+ endColumn: undefined
538
+ }
539
+ ): void {
540
+ log(
541
+ 'error',
542
+ message instanceof Error ? message.toString() : message,
543
+ properties
544
+ )
545
+ }
546
+
547
+ /**
548
+ * Logs a warning message to the console
549
+ *
550
+ * E.g. `::warning file={name},line={line},endLine={endLine},title={title}::{message}`
551
+ *
552
+ * @remarks
553
+ *
554
+ * - Uses custom logging utility function.
555
+ *
556
+ * @param message The message to log
557
+ * @param properties The annotation properties
558
+ * @returns void
559
+ */
560
+ export function warning(
561
+ message: string | Error,
562
+ properties: AnnotationProperties = {
563
+ title: undefined,
564
+ file: undefined,
565
+ startLine: undefined,
566
+ endLine: undefined,
567
+ startColumn: undefined,
568
+ endColumn: undefined
569
+ }
570
+ ): void {
571
+ log(
572
+ 'warning',
573
+ message instanceof Error ? message.toString() : message,
574
+ properties
575
+ )
576
+ }
577
+
578
+ /**
579
+ * Logs a notice message to the console
580
+ *
581
+ * E.g. `::notice file={name},line={line},endLine={endLine},title={title}::{message}`
582
+ *
583
+ * @remarks
584
+ *
585
+ * - Uses custom logging utility function.
586
+ *
587
+ * @param message The message to log
588
+ * @param properties The annotation properties
589
+ * @returns void
590
+ */
591
+ export function notice(
592
+ message: string | Error,
593
+ properties: AnnotationProperties = {
594
+ title: undefined,
595
+ file: undefined,
596
+ startLine: undefined,
597
+ endLine: undefined,
598
+ startColumn: undefined,
599
+ endColumn: undefined
600
+ }
601
+ ): void {
602
+ log(
603
+ 'notice',
604
+ message instanceof Error ? message.toString() : message,
605
+ properties
606
+ )
607
+ }
608
+
609
+ /**
610
+ * Logs an info message to the console
611
+ *
612
+ * E.g. `::info::{message}`
613
+ *
614
+ * @remarks
615
+ *
616
+ * - Uses custom logging utility function.
617
+ *
618
+ * @param message The message to log
619
+ * @returns void
620
+ */
621
+ export function info(message: string): void {
622
+ log('info', message)
623
+ }
624
+
625
+ /**
626
+ * Starts a group of log lines
627
+ *
628
+ * @remarks
629
+ *
630
+ * - Uses custom logging utility function.
631
+ *
632
+ * @param title The title of the group
633
+ * @returns void
634
+ */
635
+ export function startGroup(title: string): void {
636
+ log('group', title, {
637
+ title: undefined,
638
+ file: undefined,
639
+ startLine: undefined,
640
+ endLine: undefined,
641
+ startColumn: undefined,
642
+ endColumn: undefined
643
+ })
644
+ }
645
+
646
+ /**
647
+ * Ends a group of log lines
648
+ *
649
+ * @remarks
650
+ *
651
+ * - Uses custom logging utility function.
652
+ *
653
+ * @param title The title of the group
654
+ * @returns void
655
+ */
656
+ export function endGroup(): void {
657
+ log('endgroup', undefined, {
658
+ title: undefined,
659
+ file: undefined,
660
+ startLine: undefined,
661
+ endLine: undefined,
662
+ startColumn: undefined,
663
+ endColumn: undefined
664
+ })
665
+ }
666
+
667
+ /**
668
+ * Wraps an asynchronous function call in a group
669
+ *
670
+ * @remarks
671
+ *
672
+ * - Uses custom logging utility function.
673
+ *
674
+ * @param name The name of the group
675
+ * @param fn The function to call
676
+ * @returns A promise that resolves the result of the function
677
+ */
678
+ export async function group<T>(name: string, fn: () => Promise<T>): Promise<T> {
679
+ // Start the group
680
+ startGroup(name)
681
+
682
+ let result: T
683
+
684
+ try {
685
+ // Await the function
686
+ result = await fn()
687
+ } finally {
688
+ endGroup()
689
+ }
690
+
691
+ return result
692
+ }
693
+
694
+ //-----------------------------------------------------------------------
695
+ // Wrapper action state
696
+ //-----------------------------------------------------------------------
697
+
698
+ /**
699
+ * Save the state of the action.
700
+ *
701
+ * @remarks
702
+ *
703
+ * - Saves the value to core metadata.
704
+ *
705
+ * @param name The name of the state
706
+ * @param value The value of the state
707
+ * @returns void
708
+ */
709
+ export function saveState(name: string, value: unknown): void {
710
+ if (value === undefined || value === null) CoreMeta.state[name] = ''
711
+ else if (typeof value === 'string' || value instanceof String)
712
+ CoreMeta.state[name] = value as string
713
+ else CoreMeta.state[name] = JSON.stringify(value)
714
+ }
715
+
716
+ /**
717
+ * Get the state for the action.
718
+ *
719
+ * @remarks
720
+ *
721
+ * - Gets the value from core metadata.
722
+ *
723
+ * @param name The name of the state
724
+ * @returns The value of the state
725
+ */
726
+ export function getState(name: string): string {
727
+ return CoreMeta.state[name] || ''
728
+ }
729
+
730
+ /**
731
+ * Gets an OIDC token
732
+ *
733
+ * @remarks
734
+ *
735
+ * - Not yet implemented.
736
+ *
737
+ * @param aud The audience for the token
738
+ * @returns A promise that resolves the OIDC token
739
+ */
740
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
741
+ export async function getIDToken(aud?: string): Promise<string> {
742
+ throw new Error('Not implemented')
743
+ }