@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,340 @@
1
+ import { jest } from '@jest/globals'
2
+ import * as core from '../../../../__fixtures__/@actions/core.js'
3
+ import { ResetCoreMetadata } from '../../../../src/stubs/core/core.js'
4
+ import { EnvMeta, ResetEnvMetadata } from '../../../../src/stubs/env.js'
5
+
6
+ const isGhes = jest.fn().mockReturnValue(false)
7
+ const getGitHubWorkspaceDir = jest.fn().mockReturnValue('/github/workspace')
8
+ const getUploadChunkSize = jest.fn().mockReturnValue(8 * 1024 * 1024)
9
+ const uploadArtifact = jest.fn()
10
+ const downloadArtifactInternal = jest.fn()
11
+ const downloadArtifactPublic = jest.fn()
12
+ const listArtifactsInternal = jest.fn()
13
+ const listArtifactsPublic = jest.fn()
14
+ const getArtifactInternal = jest.fn()
15
+ const getArtifactPublic = jest.fn()
16
+ const deleteArtifactInternal = jest.fn()
17
+ const deleteArtifactPublic = jest.fn()
18
+
19
+ jest.unstable_mockModule(
20
+ '../../../../src/stubs/artifact/internal/shared/config.js',
21
+ () => ({
22
+ isGhes,
23
+ getGitHubWorkspaceDir,
24
+ getUploadChunkSize
25
+ })
26
+ )
27
+ jest.unstable_mockModule(
28
+ '../../../../src/stubs/artifact/internal/upload/upload-artifact.js',
29
+ () => ({
30
+ uploadArtifact
31
+ })
32
+ )
33
+ jest.unstable_mockModule(
34
+ '../../../../src/stubs/artifact/internal/download/download-artifact.js',
35
+ () => ({
36
+ downloadArtifactPublic,
37
+ downloadArtifactInternal
38
+ })
39
+ )
40
+ jest.unstable_mockModule(
41
+ '../../../../src/stubs/artifact/internal/find/list-artifacts.js',
42
+ () => ({
43
+ listArtifactsInternal,
44
+ listArtifactsPublic
45
+ })
46
+ )
47
+ jest.unstable_mockModule(
48
+ '../../../../src/stubs/artifact/internal/find/get-artifact.js',
49
+ () => ({
50
+ getArtifactInternal,
51
+ getArtifactPublic
52
+ })
53
+ )
54
+ jest.unstable_mockModule(
55
+ '../../../../src/stubs/artifact/internal/delete/delete-artifact.js',
56
+ () => ({
57
+ deleteArtifactInternal,
58
+ deleteArtifactPublic
59
+ })
60
+ )
61
+ jest.unstable_mockModule('../../../../src/stubs/core/core.js', () => core)
62
+
63
+ const { DefaultArtifactClient } =
64
+ await import('../../../../src/stubs/artifact/internal/client.js')
65
+
66
+ describe('DefaultArtifactClient', () => {
67
+ beforeEach(() => {
68
+ // Set environment variables
69
+ process.env.LOCAL_ACTION_WORKSPACE = '/tmp/artifacts'
70
+ process.env.LOCAL_ACTION_ARTIFACT_PATH = '/tmp/artifacts'
71
+
72
+ // Reset metadata
73
+ ResetEnvMetadata()
74
+ ResetCoreMetadata()
75
+
76
+ EnvMeta.artifacts = [{ name: 'artifact-name', id: 1, size: 0 }]
77
+ })
78
+
79
+ afterEach(() => {
80
+ jest.resetAllMocks()
81
+
82
+ // Unset environment variables
83
+ delete process.env.LOCAL_ACTION_WORKSPACE
84
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
85
+ })
86
+
87
+ describe('uploadArtifact', () => {
88
+ it('Throws if LOCAL_ACTION_WORKSPACE is not set', async () => {
89
+ delete process.env.LOCAL_ACTION_WORKSPACE
90
+
91
+ const client = new DefaultArtifactClient()
92
+
93
+ await expect(
94
+ client.uploadArtifact('artifact-name', ['file1', 'file2'], 'root')
95
+ ).rejects.toThrow(
96
+ 'LOCAL_ACTION_WORKSPACE must be set when interacting with @actions/artifact!'
97
+ )
98
+ })
99
+
100
+ it('Throws if LOCAL_ACTION_ARTIFACT_PATH is not set', async () => {
101
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
102
+
103
+ const client = new DefaultArtifactClient()
104
+
105
+ await expect(
106
+ client.uploadArtifact('artifact-name', ['file1', 'file2'], 'root')
107
+ ).rejects.toThrow()
108
+ })
109
+
110
+ it('Throws if running on GHES', async () => {
111
+ isGhes.mockReturnValue(true)
112
+
113
+ const client = new DefaultArtifactClient()
114
+
115
+ await expect(
116
+ client.uploadArtifact('artifact-name', ['file1', 'file2'], 'root')
117
+ ).rejects.toThrow()
118
+ })
119
+
120
+ it('Uploads an artifact', async () => {
121
+ const client = new DefaultArtifactClient()
122
+
123
+ await client.uploadArtifact('artifact-name', ['file1', 'file2'], 'root')
124
+
125
+ expect(uploadArtifact).toHaveBeenCalled()
126
+ })
127
+ })
128
+
129
+ describe('downloadArtifact', () => {
130
+ it('Throws if LOCAL_ACTION_WORKSPACE is not set', async () => {
131
+ delete process.env.LOCAL_ACTION_WORKSPACE
132
+
133
+ const client = new DefaultArtifactClient()
134
+
135
+ await expect(client.downloadArtifact(1)).rejects.toThrow(
136
+ 'LOCAL_ACTION_WORKSPACE must be set when interacting with @actions/artifact!'
137
+ )
138
+ })
139
+
140
+ it('Throws if LOCAL_ACTION_ARTIFACT_PATH is not set', async () => {
141
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
142
+
143
+ const client = new DefaultArtifactClient()
144
+
145
+ await expect(client.downloadArtifact(1)).rejects.toThrow()
146
+ })
147
+
148
+ it('Throws if running on GHES', async () => {
149
+ isGhes.mockReturnValue(true)
150
+
151
+ const client = new DefaultArtifactClient()
152
+
153
+ await expect(client.downloadArtifact(1)).rejects.toThrow()
154
+ })
155
+
156
+ it('Downloads an artifact (internal)', async () => {
157
+ const client = new DefaultArtifactClient()
158
+
159
+ await client.downloadArtifact(1)
160
+
161
+ expect(downloadArtifactInternal).toHaveBeenCalled()
162
+ expect(downloadArtifactPublic).not.toHaveBeenCalled()
163
+ })
164
+
165
+ it('Downloads an artifact (public)', async () => {
166
+ const client = new DefaultArtifactClient()
167
+
168
+ await client.downloadArtifact(1, {
169
+ findBy: {
170
+ repositoryOwner: 'owner',
171
+ repositoryName: 'repo',
172
+ workflowRunId: 1,
173
+ token: 'token'
174
+ }
175
+ })
176
+
177
+ expect(downloadArtifactInternal).not.toHaveBeenCalled()
178
+ expect(downloadArtifactPublic).toHaveBeenCalled()
179
+ })
180
+ })
181
+
182
+ describe('listArtifacts', () => {
183
+ it('Throws if LOCAL_ACTION_WORKSPACE is not set', async () => {
184
+ delete process.env.LOCAL_ACTION_WORKSPACE
185
+
186
+ const client = new DefaultArtifactClient()
187
+
188
+ await expect(client.listArtifacts()).rejects.toThrow(
189
+ 'LOCAL_ACTION_WORKSPACE must be set when interacting with @actions/artifact!'
190
+ )
191
+ })
192
+
193
+ it('Throws if LOCAL_ACTION_ARTIFACT_PATH is not set', async () => {
194
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
195
+
196
+ const client = new DefaultArtifactClient()
197
+
198
+ await expect(client.listArtifacts()).rejects.toThrow()
199
+ })
200
+
201
+ it('Throws if running on GHES', async () => {
202
+ isGhes.mockReturnValue(true)
203
+
204
+ const client = new DefaultArtifactClient()
205
+
206
+ await expect(client.listArtifacts()).rejects.toThrow()
207
+ })
208
+
209
+ it('Lists artifacts (internal)', async () => {
210
+ const client = new DefaultArtifactClient()
211
+
212
+ await client.listArtifacts()
213
+
214
+ expect(listArtifactsInternal).toHaveBeenCalled()
215
+ expect(listArtifactsPublic).not.toHaveBeenCalled()
216
+ })
217
+
218
+ it('Lists artifacts (public)', async () => {
219
+ const client = new DefaultArtifactClient()
220
+
221
+ await client.listArtifacts({
222
+ findBy: {
223
+ repositoryOwner: 'owner',
224
+ repositoryName: 'repo',
225
+ workflowRunId: 1,
226
+ token: 'token'
227
+ }
228
+ })
229
+
230
+ expect(listArtifactsInternal).not.toHaveBeenCalled()
231
+ expect(listArtifactsPublic).toHaveBeenCalled()
232
+ })
233
+ })
234
+
235
+ describe('getArtifact', () => {
236
+ it('Throws if LOCAL_ACTION_WORKSPACE is not set', async () => {
237
+ delete process.env.LOCAL_ACTION_WORKSPACE
238
+
239
+ const client = new DefaultArtifactClient()
240
+
241
+ await expect(client.getArtifact('artifact-name')).rejects.toThrow(
242
+ 'LOCAL_ACTION_WORKSPACE must be set when interacting with @actions/artifact!'
243
+ )
244
+ })
245
+
246
+ it('Throws if LOCAL_ACTION_ARTIFACT_PATH is not set', async () => {
247
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
248
+
249
+ const client = new DefaultArtifactClient()
250
+
251
+ await expect(client.getArtifact('artifact-name')).rejects.toThrow()
252
+ })
253
+
254
+ it('Throws if running on GHES', async () => {
255
+ isGhes.mockReturnValue(true)
256
+
257
+ const client = new DefaultArtifactClient()
258
+
259
+ await expect(client.getArtifact('artifact-name')).rejects.toThrow()
260
+ })
261
+
262
+ it('Gets an artifact (internal)', async () => {
263
+ const client = new DefaultArtifactClient()
264
+
265
+ await client.getArtifact('artifact-name')
266
+
267
+ expect(getArtifactInternal).toHaveBeenCalled()
268
+ expect(getArtifactPublic).not.toHaveBeenCalled()
269
+ })
270
+
271
+ it('Gets an artifact (public)', async () => {
272
+ const client = new DefaultArtifactClient()
273
+
274
+ await client.getArtifact('artifact-name', {
275
+ findBy: {
276
+ repositoryOwner: 'owner',
277
+ repositoryName: 'repo',
278
+ workflowRunId: 1,
279
+ token: 'token'
280
+ }
281
+ })
282
+
283
+ expect(getArtifactInternal).not.toHaveBeenCalled()
284
+ expect(getArtifactPublic).toHaveBeenCalled()
285
+ })
286
+ })
287
+
288
+ describe('deleteArtifact', () => {
289
+ it('Throws if LOCAL_ACTION_WORKSPACE is not set', async () => {
290
+ delete process.env.LOCAL_ACTION_WORKSPACE
291
+
292
+ const client = new DefaultArtifactClient()
293
+
294
+ await expect(client.deleteArtifact('artifact-name')).rejects.toThrow(
295
+ 'LOCAL_ACTION_WORKSPACE must be set when interacting with @actions/artifact!'
296
+ )
297
+ })
298
+
299
+ it('Throws if LOCAL_ACTION_ARTIFACT_PATH is not set', async () => {
300
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
301
+
302
+ const client = new DefaultArtifactClient()
303
+
304
+ await expect(client.deleteArtifact('artifact-name')).rejects.toThrow()
305
+ })
306
+
307
+ it('Throws if running on GHES', async () => {
308
+ isGhes.mockReturnValue(true)
309
+
310
+ const client = new DefaultArtifactClient()
311
+
312
+ await expect(client.deleteArtifact('artifact-name')).rejects.toThrow()
313
+ })
314
+
315
+ it('Deletes an artifact (internal)', async () => {
316
+ const client = new DefaultArtifactClient()
317
+
318
+ await client.deleteArtifact('artifact-name')
319
+
320
+ expect(deleteArtifactInternal).toHaveBeenCalled()
321
+ expect(deleteArtifactPublic).not.toHaveBeenCalled()
322
+ })
323
+
324
+ it('Deletes an artifact (public)', async () => {
325
+ const client = new DefaultArtifactClient()
326
+
327
+ await client.deleteArtifact('artifact-name', {
328
+ findBy: {
329
+ repositoryOwner: 'owner',
330
+ repositoryName: 'repo',
331
+ workflowRunId: 1,
332
+ token: 'token'
333
+ }
334
+ })
335
+
336
+ expect(deleteArtifactInternal).not.toHaveBeenCalled()
337
+ expect(deleteArtifactPublic).toHaveBeenCalled()
338
+ })
339
+ })
340
+ })
@@ -0,0 +1,152 @@
1
+ import { jest } from '@jest/globals'
2
+ import * as core from '../../../../../__fixtures__/@actions/core.js'
3
+ import * as github from '../../../../../__fixtures__/@actions/github.js'
4
+ import * as octokit from '../../../../../__fixtures__/@octokit/rest.js'
5
+ import * as fs from '../../../../../__fixtures__/fs.js'
6
+ import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js'
7
+ import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js'
8
+
9
+ jest.unstable_mockModule('@octokit/rest', async () => {
10
+ class Octokit {
11
+ constructor() {
12
+ return octokit
13
+ }
14
+ }
15
+
16
+ return {
17
+ Octokit
18
+ }
19
+ })
20
+ jest.unstable_mockModule('fs', () => fs)
21
+
22
+ const getArtifactPublic =
23
+ jest.fn<
24
+ typeof import('../../../../../src/stubs/artifact/internal/find/get-artifact.js').getArtifactPublic
25
+ >()
26
+
27
+ jest.unstable_mockModule(
28
+ '../../../../../src/stubs/artifact/internal/find/get-artifact.js',
29
+ () => ({
30
+ getArtifactPublic
31
+ })
32
+ )
33
+ jest.unstable_mockModule('../../../../../src/stubs/core/core.js', () => core)
34
+ jest.unstable_mockModule(
35
+ '../../../../../src/stubs/github/github.js',
36
+ () => github
37
+ )
38
+
39
+ const deleteArtifact =
40
+ await import('../../../../../src/stubs/artifact/internal/delete/delete-artifact.js')
41
+
42
+ const { Octokit } = await import('@octokit/rest')
43
+ const mocktokit = jest.mocked(new Octokit())
44
+
45
+ describe('delete-artifact', () => {
46
+ beforeEach(() => {
47
+ // Reset metadata
48
+ ResetEnvMetadata()
49
+ ResetCoreMetadata()
50
+
51
+ // Set environment variables
52
+ process.env.LOCAL_ACTION_ARTIFACT_PATH = '/tmp/artifacts'
53
+ })
54
+
55
+ afterEach(() => {
56
+ jest.resetAllMocks()
57
+
58
+ // Unset environment variables
59
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
60
+ })
61
+
62
+ describe('deleteArtifactPublic', () => {
63
+ beforeEach(() => {
64
+ getArtifactPublic.mockResolvedValue({
65
+ artifact: {
66
+ name: 'artifact-name',
67
+ id: 1,
68
+ size: 0
69
+ }
70
+ })
71
+ })
72
+
73
+ it('Deletes an artifact', async () => {
74
+ mocktokit.rest.actions.deleteArtifact.mockResolvedValue({
75
+ status: 204,
76
+ headers: {
77
+ 'x-github-request-id': 'request-id'
78
+ }
79
+ } as any)
80
+
81
+ const response = await deleteArtifact.deleteArtifactPublic(
82
+ 'artifact-name',
83
+ 1,
84
+ 'owner',
85
+ 'repo',
86
+ 'token'
87
+ )
88
+
89
+ expect(getArtifactPublic).toHaveBeenCalledTimes(1)
90
+ expect(mocktokit.rest.actions.deleteArtifact).toHaveBeenCalledTimes(1)
91
+ expect(response).toMatchObject({
92
+ id: 1
93
+ })
94
+ })
95
+
96
+ it('Throws if artifact fails to delete', async () => {
97
+ mocktokit.rest.actions.deleteArtifact.mockResolvedValue({
98
+ status: 400,
99
+ headers: {
100
+ 'x-github-request-id': 'request-id'
101
+ }
102
+ } as any)
103
+
104
+ await expect(
105
+ deleteArtifact.deleteArtifactPublic(
106
+ 'artifact-name',
107
+ 1,
108
+ 'owner',
109
+ 'repo',
110
+ 'token'
111
+ )
112
+ ).rejects.toThrow('Invalid response from GitHub API: 400 (request-id)')
113
+ })
114
+ })
115
+
116
+ describe('deleteArtifactInternal', () => {
117
+ it('Deletes an artifact', async () => {
118
+ EnvMeta.artifacts = [{ name: 'artifact-name', id: 1, size: 0 }]
119
+
120
+ const response =
121
+ await deleteArtifact.deleteArtifactInternal('artifact-name')
122
+
123
+ expect(fs.rmSync).toHaveBeenCalledTimes(1)
124
+ expect(EnvMeta.artifacts.length).toBe(0)
125
+ expect(response).toMatchObject({
126
+ id: 1
127
+ })
128
+ })
129
+
130
+ it('Deletes the latest artifact', async () => {
131
+ EnvMeta.artifacts = [
132
+ { name: 'artifact-name', id: 1, size: 0 },
133
+ { name: 'artifact-name', id: 2, size: 0 }
134
+ ]
135
+
136
+ const response =
137
+ await deleteArtifact.deleteArtifactInternal('artifact-name')
138
+
139
+ expect(fs.rmSync).toHaveBeenCalledTimes(1)
140
+ expect(EnvMeta.artifacts.length).toBe(1)
141
+ expect(response).toMatchObject({
142
+ id: 2
143
+ })
144
+ })
145
+
146
+ it('Throws if no matching artifact is found', async () => {
147
+ await expect(
148
+ deleteArtifact.deleteArtifactInternal('artifact-name')
149
+ ).rejects.toThrow()
150
+ })
151
+ })
152
+ })
@@ -0,0 +1,119 @@
1
+ import { jest } from '@jest/globals'
2
+ import * as core from '../../../../../__fixtures__/@actions/core.js'
3
+ import * as crypto from '../../../../../__fixtures__/crypto.js'
4
+ import * as fs from '../../../../../__fixtures__/fs.js'
5
+ import * as stream from '../../../../../__fixtures__/stream/promises.js'
6
+ import { ResetCoreMetadata } from '../../../../../src/stubs/core/core.js'
7
+ import { EnvMeta, ResetEnvMetadata } from '../../../../../src/stubs/env.js'
8
+
9
+ const readStream = {
10
+ on: () => readStream,
11
+ pipe: () => readStream
12
+ }
13
+
14
+ jest.unstable_mockModule('crypto', () => crypto)
15
+ jest.unstable_mockModule('fs', () => fs)
16
+ jest.unstable_mockModule('stream/promises', () => stream)
17
+
18
+ jest.unstable_mockModule('../../../../../src/stubs/core/core.js', () => core)
19
+
20
+ const downloadArtifact =
21
+ await import('../../../../../src/stubs/artifact/internal/download/download-artifact.js')
22
+
23
+ describe('download-artifact', () => {
24
+ beforeEach(() => {
25
+ // Reset environment variables
26
+ process.env.LOCAL_ACTION_ARTIFACT_PATH = '/tmp/artifacts'
27
+
28
+ // Reset metadata
29
+ ResetEnvMetadata()
30
+ ResetCoreMetadata()
31
+
32
+ // Reset mocks
33
+ fs.createReadStream.mockImplementation(() => readStream)
34
+
35
+ EnvMeta.artifacts = [{ name: 'artifact-name', id: 1, size: 0 }]
36
+ })
37
+
38
+ afterEach(() => {
39
+ jest.resetAllMocks()
40
+
41
+ // Unset environment variables
42
+ delete process.env.LOCAL_ACTION_ARTIFACT_PATH
43
+ })
44
+
45
+ describe('scrubQueryParameters', () => {
46
+ it('Scrubs query parameters from a URL', () => {
47
+ const url = 'https://example.com?foo=bar&baz=qux'
48
+ const scrubbedUrl = downloadArtifact.scrubQueryParameters(url)
49
+ expect(scrubbedUrl).toBe('https://example.com/')
50
+ })
51
+ })
52
+
53
+ describe('exists', () => {
54
+ it('Returns true if the path exists', () => {
55
+ fs.accessSync.mockReturnValue(undefined)
56
+ const result = downloadArtifact.exists('/tmp/artifacts')
57
+ expect(result).toBe(true)
58
+ })
59
+
60
+ it('Returns false if the path does not exist', () => {
61
+ fs.accessSync.mockImplementation(() => {
62
+ throw { code: 'ENOENT' }
63
+ })
64
+ const result = downloadArtifact.exists('/tmp/artifacts')
65
+ expect(result).toBe(false)
66
+ })
67
+
68
+ it('Throws if an error other than ENOENT occurs', () => {
69
+ fs.accessSync.mockReset().mockImplementation(() => {
70
+ throw { code: 'EPERM' }
71
+ })
72
+ expect(() => downloadArtifact.exists('/tmp/artifacts')).toThrow()
73
+ })
74
+ })
75
+
76
+ describe('downloadArtifactInternal', () => {
77
+ it('Downloads an artifact', async () => {
78
+ await downloadArtifact.downloadArtifactInternal(1)
79
+
80
+ expect(fs.createReadStream).toHaveBeenCalledTimes(1)
81
+ expect(stream.finished).toHaveBeenCalledTimes(1)
82
+ })
83
+
84
+ it('Downloads the first artifact if multiple are found', async () => {
85
+ EnvMeta.artifacts = [
86
+ { name: 'artifact-name-1', id: 1, size: 0 },
87
+ { name: 'artifact-name-2', id: 1, size: 0 }
88
+ ]
89
+
90
+ await downloadArtifact.downloadArtifactInternal(1)
91
+
92
+ expect(fs.createReadStream).toHaveBeenCalledTimes(1)
93
+ expect(fs.createReadStream).toHaveBeenCalledWith(
94
+ '/tmp/artifacts/artifact-name-1.zip'
95
+ )
96
+ expect(stream.finished).toHaveBeenCalledTimes(1)
97
+ })
98
+
99
+ it('Throws if an artifact is not found', async () => {
100
+ EnvMeta.artifacts = []
101
+
102
+ await expect(
103
+ downloadArtifact.downloadArtifactInternal(1)
104
+ ).rejects.toThrow()
105
+ })
106
+
107
+ it('Throws if an error occurs while downloading', async () => {
108
+ fs.createReadStream.mockImplementation(() => {
109
+ throw new Error('Download error')
110
+ })
111
+
112
+ await expect(
113
+ downloadArtifact.downloadArtifactInternal(1)
114
+ ).rejects.toThrow(
115
+ 'Unable to download and extract artifact: Download error'
116
+ )
117
+ })
118
+ })
119
+ })