@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,45 @@
1
+ /**
2
+ * Last Reviewed Commit: b2557ac90ca11aad2f3dfb23565c54e91cef5dfe
3
+ * Last Reviewed Date: 2026-01-16
4
+ */
5
+
6
+ export enum CacheFilename {
7
+ Gzip = 'cache.tgz',
8
+ Zstd = 'cache.tzst'
9
+ }
10
+
11
+ export enum CompressionMethod {
12
+ Gzip = 'gzip',
13
+ // Long range mode was added to zstd in v1.3.2.
14
+ // This enum is for earlier version of zstd that does not have --long support
15
+ ZstdWithoutLong = 'zstd-without-long',
16
+ Zstd = 'zstd'
17
+ }
18
+
19
+ export enum ArchiveToolType {
20
+ GNU = 'gnu',
21
+ BSD = 'bsd'
22
+ }
23
+
24
+ // The default number of retry attempts.
25
+ export const DefaultRetryAttempts = 2
26
+
27
+ // The default delay in milliseconds between retry attempts.
28
+ export const DefaultRetryDelay = 5000
29
+
30
+ // Socket timeout in milliseconds during download. If no traffic is received
31
+ // over the socket during this period, the socket is destroyed and the download
32
+ // is aborted.
33
+ export const SocketTimeout = 5000
34
+
35
+ // The default path of GNUtar on hosted Windows runners
36
+ export const GnuTarPathOnWindows = `${process.env['PROGRAMFILES']}\\Git\\usr\\bin\\tar.exe`
37
+
38
+ // The default path of BSDtar on hosted Windows runners
39
+ export const SystemTarPathOnWindows = `${process.env['SYSTEMDRIVE']}\\Windows\\System32\\tar.exe`
40
+
41
+ export const TarFilename = 'cache.tar'
42
+
43
+ export const ManifestFilename = 'manifest.txt'
44
+
45
+ export const CacheFileSizeLimit = 10 * Math.pow(1024, 3) // 10GiB per repository
@@ -0,0 +1,374 @@
1
+ /**
2
+ * Last Reviewed Commit: ea21da69936b05b9a4e65cd3be2b054bf3a6db23
3
+ * Last Reviewed Date: 2025-01-16
4
+ */
5
+
6
+ import { exec } from '@actions/exec'
7
+ import * as io from '@actions/io'
8
+ import { existsSync, writeFileSync } from 'fs'
9
+ import * as path from 'path'
10
+ import { ArchiveTool } from '../interfaces.js'
11
+ import * as utils from './cacheUtils.js'
12
+ import {
13
+ ArchiveToolType,
14
+ CompressionMethod,
15
+ ManifestFilename,
16
+ SystemTarPathOnWindows,
17
+ TarFilename
18
+ } from './constants.js'
19
+
20
+ const IS_WINDOWS = process.platform === 'win32'
21
+
22
+ /**
23
+ * Returns tar path and type: BSD or GNU
24
+ *
25
+ * @returns Path and type of tar
26
+ */
27
+ /* istanbul ignore next */
28
+ async function getTarPath(): Promise<ArchiveTool> {
29
+ switch (process.platform) {
30
+ case 'win32': {
31
+ const gnuTar = await utils.getGnuTarPathOnWindows()
32
+ const systemTar = SystemTarPathOnWindows
33
+ if (gnuTar) {
34
+ // Use GNUtar as default on windows
35
+ return <ArchiveTool>{ path: gnuTar, type: ArchiveToolType.GNU }
36
+ } else if (existsSync(systemTar)) {
37
+ return <ArchiveTool>{ path: systemTar, type: ArchiveToolType.BSD }
38
+ }
39
+ break
40
+ }
41
+ case 'darwin': {
42
+ const gnuTar = await io.which('gtar', false)
43
+ if (gnuTar) {
44
+ // fix permission denied errors when extracting BSD tar archive with GNU tar - https://github.com/actions/cache/issues/527
45
+ return <ArchiveTool>{ path: gnuTar, type: ArchiveToolType.GNU }
46
+ } else {
47
+ return <ArchiveTool>{
48
+ path: await io.which('tar', true),
49
+ type: ArchiveToolType.BSD
50
+ }
51
+ }
52
+ }
53
+ default:
54
+ break
55
+ }
56
+ // Default assumption is GNU tar is present in path
57
+ return <ArchiveTool>{
58
+ path: await io.which('tar', true),
59
+ type: ArchiveToolType.GNU
60
+ }
61
+ }
62
+
63
+ /**
64
+ * Return arguments for tar as per tarPath, compressionMethod, method type and os
65
+ *
66
+ * @param tarPath Path and type of tar
67
+ * @param compressionMethod Compression method
68
+ * @param type Type of operation: create, extract, list
69
+ * @param archivePath Archive path for extract and list operations
70
+ * @returns List of arguments for tar command
71
+ *
72
+ * @remarks
73
+ *
74
+ * - Made archivePath required for create operation
75
+ * - Removed exclude statement for creation since it happens in a different path
76
+ */
77
+ async function getTarArgs(
78
+ tarPath: ArchiveTool,
79
+ compressionMethod: CompressionMethod,
80
+ type: string,
81
+ archivePath: string
82
+ ): Promise<string[]> {
83
+ const args = [`"${tarPath.path}"`]
84
+ const cacheFileName = utils.getCacheFileName(compressionMethod)
85
+ const tarFile = 'cache.tar'
86
+ const workingDirectory = getWorkingDirectory()
87
+
88
+ // Speficic args for BSD tar on windows for workaround
89
+ /* istanbul ignore next */
90
+ const BSD_TAR_ZSTD =
91
+ tarPath.type === ArchiveToolType.BSD &&
92
+ compressionMethod !== CompressionMethod.Gzip &&
93
+ IS_WINDOWS
94
+
95
+ // Method specific args
96
+ switch (type) {
97
+ case 'create':
98
+ args.push(
99
+ '--posix',
100
+ '-cf',
101
+ /* istanbul ignore next */
102
+ BSD_TAR_ZSTD
103
+ ? tarFile
104
+ : path
105
+ .join(archivePath, cacheFileName)
106
+ .replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
107
+ '-P',
108
+ '-C',
109
+ workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
110
+ '--files-from',
111
+ path.join(process.env.LOCAL_ACTION_WORKSPACE!, ManifestFilename)
112
+ )
113
+ break
114
+ case 'extract':
115
+ args.push(
116
+ '-xf',
117
+ /* istanbul ignore next */
118
+ BSD_TAR_ZSTD
119
+ ? tarFile
120
+ : archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
121
+ '-P',
122
+ '-C',
123
+ workingDirectory.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
124
+ )
125
+ break
126
+ case 'list':
127
+ args.push(
128
+ '-tf',
129
+ /* istanbul ignore next */
130
+ BSD_TAR_ZSTD
131
+ ? tarFile
132
+ : archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
133
+ '-P'
134
+ )
135
+ break
136
+ }
137
+
138
+ // Platform specific args
139
+ /* istanbul ignore next */
140
+ if (tarPath.type === ArchiveToolType.GNU) {
141
+ switch (process.platform) {
142
+ case 'win32':
143
+ args.push('--force-local')
144
+ break
145
+ case 'darwin':
146
+ args.push('--delay-directory-restore')
147
+ break
148
+ }
149
+ }
150
+
151
+ return args
152
+ }
153
+
154
+ /**
155
+ * Returns commands to run TAR and compression program
156
+ *
157
+ * @param compressionMethod Compression method
158
+ * @param type Type of operation: create, extract, list
159
+ * @param archivePath Archive path for create, extract, and list operations
160
+ * @returns List of commands to run
161
+ */
162
+ /* istanbul ignore next */
163
+ async function getCommands(
164
+ compressionMethod: CompressionMethod,
165
+ type: string,
166
+ archivePath = ''
167
+ ): Promise<string[]> {
168
+ let args
169
+
170
+ const tarPath = await getTarPath()
171
+ const tarArgs = await getTarArgs(
172
+ tarPath,
173
+ compressionMethod,
174
+ type,
175
+ archivePath
176
+ )
177
+
178
+ const compressionArgs =
179
+ type !== 'create'
180
+ ? await getDecompressionProgram(tarPath, compressionMethod, archivePath)
181
+ : await getCompressionProgram(tarPath, compressionMethod)
182
+
183
+ const BSD_TAR_ZSTD =
184
+ tarPath.type === ArchiveToolType.BSD &&
185
+ compressionMethod !== CompressionMethod.Gzip &&
186
+ IS_WINDOWS
187
+
188
+ if (BSD_TAR_ZSTD && type !== 'create')
189
+ args = [[...compressionArgs].join(' '), [...tarArgs].join(' ')]
190
+ else args = [[...tarArgs].join(' '), [...compressionArgs].join(' ')]
191
+
192
+ if (BSD_TAR_ZSTD) return args
193
+
194
+ return [args.join(' ')]
195
+ }
196
+
197
+ /**
198
+ * Gets the working directory (local or GitHub Actions)
199
+ *
200
+ * @returns Working directory
201
+ */
202
+ /* istanbul ignore next */
203
+ function getWorkingDirectory(): string {
204
+ return process.env.GITHUB_WORKSPACE ?? process.cwd()
205
+ }
206
+
207
+ /**
208
+ * Common function for extractTar and listTar to get the compression method
209
+ *
210
+ * @param tarPath Path and type of tar
211
+ * @param compressionMethod Compression method
212
+ * @param archivePath Archive path for extract and list operations
213
+ * @returns List of arguments for decompression program
214
+ */
215
+ /* istanbul ignore next */
216
+ async function getDecompressionProgram(
217
+ tarPath: ArchiveTool,
218
+ compressionMethod: CompressionMethod,
219
+ archivePath: string
220
+ ): Promise<string[]> {
221
+ // -d: Decompress.
222
+ // unzstd is equivalent to 'zstd -d'
223
+ // --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
224
+ // Using 30 here because we also support 32-bit self-hosted runners.
225
+ const BSD_TAR_ZSTD =
226
+ tarPath.type === ArchiveToolType.BSD &&
227
+ compressionMethod !== CompressionMethod.Gzip &&
228
+ IS_WINDOWS
229
+ switch (compressionMethod) {
230
+ case CompressionMethod.Zstd:
231
+ return BSD_TAR_ZSTD
232
+ ? [
233
+ 'zstd -d --long=30 --force -o',
234
+ TarFilename,
235
+ archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
236
+ ]
237
+ : [
238
+ '--use-compress-program',
239
+ IS_WINDOWS ? '"zstd -d --long=30"' : 'unzstd --long=30'
240
+ ]
241
+ case CompressionMethod.ZstdWithoutLong:
242
+ return BSD_TAR_ZSTD
243
+ ? [
244
+ 'zstd -d --force -o',
245
+ TarFilename,
246
+ archivePath.replace(new RegExp(`\\${path.sep}`, 'g'), '/')
247
+ ]
248
+ : ['--use-compress-program', IS_WINDOWS ? '"zstd -d"' : 'unzstd']
249
+ default:
250
+ return ['-z']
251
+ }
252
+ }
253
+
254
+ /**
255
+ * Used for creating the archive
256
+ *
257
+ * -T#: Compress using # working thread. If # is 0, attempt to detect and use the number of physical CPU cores.
258
+ * zstdmt is equivalent to 'zstd -T0'
259
+ * --long=#: Enables long distance matching with # bits. Maximum is 30 (1GB) on 32-bit OS and 31 (2GB) on 64-bit.
260
+ * Using 30 here because we also support 32-bit self-hosted runners.
261
+ * Long range mode is added to zstd in v1.3.2 release, so we will not use --long in older version of zstd.
262
+ */
263
+ /* istanbul ignore next */
264
+ async function getCompressionProgram(
265
+ tarPath: ArchiveTool,
266
+ compressionMethod: CompressionMethod
267
+ ): Promise<string[]> {
268
+ const cacheFileName = utils.getCacheFileName(compressionMethod)
269
+ const BSD_TAR_ZSTD =
270
+ tarPath.type === ArchiveToolType.BSD &&
271
+ compressionMethod !== CompressionMethod.Gzip &&
272
+ IS_WINDOWS
273
+ switch (compressionMethod) {
274
+ case CompressionMethod.Zstd:
275
+ return BSD_TAR_ZSTD
276
+ ? [
277
+ 'zstd -T0 --long=30 --force -o',
278
+ cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
279
+ TarFilename
280
+ ]
281
+ : [
282
+ '--use-compress-program',
283
+ IS_WINDOWS ? '"zstd -T0 --long=30"' : 'zstdmt --long=30'
284
+ ]
285
+ case CompressionMethod.ZstdWithoutLong:
286
+ return BSD_TAR_ZSTD
287
+ ? [
288
+ 'zstd -T0 --force -o',
289
+ cacheFileName.replace(new RegExp(`\\${path.sep}`, 'g'), '/'),
290
+ TarFilename
291
+ ]
292
+ : ['--use-compress-program', IS_WINDOWS ? '"zstd -T0"' : 'zstdmt']
293
+ default:
294
+ return ['-z']
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Executes all commands as separate processes
300
+ *
301
+ * @param commands List of commands to execute
302
+ * @param cwd Optional current working directory for the commands
303
+ */
304
+ /* istanbul ignore next */
305
+ async function execCommands(commands: string[], cwd?: string): Promise<void> {
306
+ for (const command of commands) {
307
+ try {
308
+ await exec(command, undefined, {
309
+ cwd,
310
+ env: { ...(process.env as object), MSYS: 'winsymlinks:nativestrict' }
311
+ })
312
+ } catch (error: any) {
313
+ throw new Error(
314
+ `${command.split(' ')[0]} failed with error: ${error?.message}`,
315
+ { cause: error }
316
+ )
317
+ }
318
+ }
319
+ }
320
+
321
+ /**
322
+ * List the contents of a tar
323
+ *
324
+ * @param archivePath Path to the archive to list
325
+ * @param compressionMethod Compression method to use
326
+ */
327
+ /* istanbul ignore next */
328
+ export async function listTar(
329
+ archivePath: string,
330
+ compressionMethod: CompressionMethod
331
+ ): Promise<void> {
332
+ const commands = await getCommands(compressionMethod, 'list', archivePath)
333
+ await execCommands(commands)
334
+ }
335
+
336
+ /**
337
+ * Extracts a TAR
338
+ *
339
+ * @param archivePath Path to the archive to extract
340
+ * @param compressionMethod Compression method to use
341
+ */
342
+ /* istanbul ignore next */
343
+ export async function extractTar(
344
+ archivePath: string,
345
+ compressionMethod: CompressionMethod
346
+ ): Promise<void> {
347
+ // Create directory to extract tar into
348
+ const workingDirectory = getWorkingDirectory()
349
+ await io.mkdirP(workingDirectory)
350
+ const commands = await getCommands(compressionMethod, 'extract', archivePath)
351
+ await execCommands(commands)
352
+ }
353
+
354
+ /**
355
+ * Creates a TAR archive from a list of directories
356
+ *
357
+ * @param archiveFolder The folder where the archive will be created
358
+ * @param sourceDirectories List of directories to include in the archive
359
+ * @param compressionMethod Compression method to use
360
+ */
361
+ /* istanbul ignore next */
362
+ export async function createTar(
363
+ archiveFolder: string,
364
+ sourceDirectories: string[],
365
+ compressionMethod: CompressionMethod
366
+ ): Promise<void> {
367
+ // Write source directories to manifest.txt to avoid command length limits
368
+ writeFileSync(
369
+ path.join(process.env.LOCAL_ACTION_WORKSPACE!, ManifestFilename),
370
+ sourceDirectories.join('\n')
371
+ )
372
+ const commands = await getCommands(compressionMethod, 'create', archiveFolder)
373
+ await execCommands(commands, archiveFolder)
374
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Last Reviewed Commit: 792ec716de29f031413f3e4f810142cd223f1773
3
+ * Last Reviewed Date: 2026-01-16
4
+ *
5
+ * @remarks
6
+ *
7
+ * - Removed getUploadOptions function
8
+ * - Removed getDownloadOptions function
9
+ */
10
+
11
+ /**
12
+ * Options to control cache upload
13
+ */
14
+ export interface UploadOptions {
15
+ /**
16
+ * Indicates whether to use the Azure Blob SDK to download caches
17
+ * that are stored on Azure Blob Storage to improve reliability and
18
+ * performance
19
+ *
20
+ * @default false
21
+ */
22
+ useAzureSdk?: boolean
23
+ /**
24
+ * Number of parallel cache upload
25
+ *
26
+ * @default 4
27
+ */
28
+ uploadConcurrency?: number
29
+ /**
30
+ * Maximum chunk size in bytes for cache upload
31
+ *
32
+ * @default 32MB
33
+ */
34
+ uploadChunkSize?: number
35
+ /**
36
+ * Archive size in bytes
37
+ */
38
+ archiveSizeBytes?: number
39
+ }
40
+
41
+ /**
42
+ * Options to control cache download
43
+ */
44
+ export interface DownloadOptions {
45
+ /**
46
+ * Indicates whether to use the Azure Blob SDK to download caches
47
+ * that are stored on Azure Blob Storage to improve reliability and
48
+ * performance
49
+ *
50
+ * @default true
51
+ */
52
+ useAzureSdk?: boolean
53
+
54
+ /**
55
+ * Number of parallel downloads (this option only applies when using
56
+ * the Azure SDK)
57
+ *
58
+ * @default 8
59
+ */
60
+ downloadConcurrency?: number
61
+
62
+ /**
63
+ * Indicates whether to use Actions HttpClient with concurrency
64
+ * for Azure Blob Storage
65
+ */
66
+ concurrentBlobDownloads?: boolean
67
+
68
+ /**
69
+ * Maximum time for each download request, in milliseconds (this
70
+ * option only applies when using the Azure SDK)
71
+ *
72
+ * @default 30000
73
+ */
74
+ timeoutInMs?: number
75
+
76
+ /**
77
+ * Time after which a segment download should be aborted if stuck
78
+ *
79
+ * @default 3600000
80
+ */
81
+ segmentTimeoutInMs?: number
82
+
83
+ /**
84
+ * Weather to skip downloading the cache entry.
85
+ * If lookupOnly is set to true, the restore function will only check if
86
+ * a matching cache entry exists and return the cache key if it does.
87
+ *
88
+ * @default false
89
+ */
90
+ lookupOnly?: boolean
91
+ }