Compare commits

..

2 Commits

Author SHA1 Message Date
Daniel Kennedy e785baf943 Bump minimatch to 10.1.1 2026-02-25 14:08:44 -05:00
Daniel Kennedy 9c47937ac2 Cache licenses 2026-02-25 14:08:44 -05:00
18 changed files with 462 additions and 505 deletions
+7 -143
View File
@@ -10,10 +10,6 @@ on:
paths-ignore:
- '**.md'
permissions:
contents: read
actions: write
jobs:
build:
name: Build
@@ -98,7 +94,7 @@ jobs:
# Download Artifact #1 and verify the correctness of the content
- name: 'Download artifact #1'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: 'Artifact-A-${{ matrix.runs-on }}'
path: some/new/path
@@ -118,7 +114,7 @@ jobs:
# Download Artifact #2 and verify the correctness of the content
- name: 'Download artifact #2'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: 'Artifact-Wildcard-${{ matrix.runs-on }}'
path: some/other/path
@@ -139,7 +135,7 @@ jobs:
# Download Artifact #4 and verify the correctness of the content
- name: 'Download artifact #4'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: 'Multi-Path-Artifact-${{ matrix.runs-on }}'
path: multi/artifact
@@ -159,7 +155,7 @@ jobs:
shell: pwsh
- name: 'Download symlinked artifact'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
path: from/symlink
@@ -200,7 +196,7 @@ jobs:
# Download replaced Artifact #1 and verify the correctness of the content
- name: 'Download artifact #1 again'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: 'Artifact-A-${{ matrix.runs-on }}'
path: overwrite/some/new/path
@@ -217,101 +213,6 @@ jobs:
Write-Error "File contents of downloaded artifact are incorrect"
}
shell: pwsh
# Upload a single file without archiving (direct file upload)
- name: 'Create direct upload file'
run: echo -n 'direct file upload content' > direct-upload-${{ matrix.runs-on }}.txt
shell: bash
- name: 'Upload direct file artifact'
uses: ./
with:
name: 'Direct-File-${{ matrix.runs-on }}'
path: direct-upload-${{ matrix.runs-on }}.txt
archive: false
- name: 'Download direct file artifact'
uses: actions/download-artifact@main
with:
name: direct-upload-${{ matrix.runs-on }}.txt
path: direct-download
- name: 'Verify direct file artifact'
run: |
$file = "direct-download/direct-upload-${{ matrix.runs-on }}.txt"
if(!(Test-Path -path $file))
{
Write-Error "Expected file does not exist"
}
if(!((Get-Content $file -Raw).TrimEnd() -ceq "direct file upload content"))
{
Write-Error "File contents of downloaded artifact are incorrect"
}
shell: pwsh
upload-html-report:
name: Upload HTML Report
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node 24
uses: actions/setup-node@v4
with:
node-version: 24.x
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Compile
run: npm run build
- name: Create HTML report
run: |
cat > report.html << 'EOF'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Artifact Upload Test Report</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; max-width: 800px; margin: 40px auto; padding: 0 20px; color: #24292f; }
h1 { border-bottom: 1px solid #d0d7de; padding-bottom: 8px; }
.success { color: #1a7f37; }
.info { background: #ddf4ff; border: 1px solid #54aeff; border-radius: 6px; padding: 12px 16px; margin: 16px 0; }
table { border-collapse: collapse; width: 100%; margin: 16px 0; }
th, td { border: 1px solid #d0d7de; padding: 8px 12px; text-align: left; }
th { background: #f6f8fa; }
</style>
</head>
<body>
<h1>Artifact Upload Test Report</h1>
<div class="info">
<strong>This HTML file was uploaded as a single un-zipped artifact.</strong>
If you can see this in the browser, the feature is working correctly!
</div>
<table>
<tr><th>Property</th><th>Value</th></tr>
<tr><td>Upload method</td><td><code>archive: false</code></td></tr>
<tr><td>Content-Type</td><td><code>text/html</code></td></tr>
<tr><td>File</td><td><code>report.html</code></td></tr>
</table>
<p class="success">&#10004; Single file upload is working!</p>
</body>
</html>
EOF
- name: Upload HTML report (no archive)
uses: ./
with:
name: 'test-report'
path: report.html
archive: false
merge:
name: Merge
needs: build
@@ -329,7 +230,7 @@ jobs:
# easier to identify each of the merged artifacts
separate-directories: true
- name: 'Download merged artifacts'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: merged-artifacts
path: all-merged-artifacts
@@ -365,7 +266,7 @@ jobs:
# Download merged artifacts and verify the correctness of the content
- name: 'Download merged artifacts'
uses: actions/download-artifact@main
uses: actions/download-artifact@v4
with:
name: Merged-Artifact-As
path: merged-artifact-a
@@ -389,40 +290,3 @@ jobs:
}
shell: pwsh
cleanup:
name: Cleanup Artifacts
needs: [build, merge]
runs-on: ubuntu-latest
steps:
- name: Delete test artifacts
uses: actions/github-script@v8
with:
script: |
const keep = ['report.html'];
const owner = context.repo.owner;
const repo = context.repo.repo;
const runId = context.runId;
const {data: {artifacts}} = await github.rest.actions.listWorkflowRunArtifacts({
owner,
repo,
run_id: runId
});
for (const a of artifacts) {
if (keep.includes(a.name)) {
console.log(`Keeping artifact '${a.name}'`);
continue;
}
try {
await github.rest.actions.deleteArtifact({
owner,
repo,
artifact_id: a.id
});
console.log(`Deleted artifact '${a.name}'`);
} catch (err) {
console.log(`Could not delete artifact '${a.name}': ${err.message}`);
}
}
+34
View File
@@ -0,0 +1,34 @@
---
name: balanced-match
version: 4.0.4
type: npm
summary: Match balanced character pairs, like "{" and "}"
homepage:
license: mit
licenses:
- sources: LICENSE.md
text: |
(MIT)
Original code Copyright Julian Gruber <julian@juliangruber.com>
Port to TypeScript Copyright Isaac Z. Schlueter <i@izs.me>
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices: []
+34
View File
@@ -0,0 +1,34 @@
---
name: brace-expansion
version: 5.0.3
type: npm
summary: Brace expansion as known from sh/bash
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
MIT License
Copyright Julian Gruber <julian@juliangruber.com>
TypeScript port Copyright Isaac Z. Schlueter <i@izs.me>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices: []
+37
View File
@@ -0,0 +1,37 @@
---
name: fast-content-type-parse
version: 3.0.0
type: npm
summary: Parse HTTP Content-Type header according to RFC 7231
homepage: https://github.com/fastify/fast-content-type-parse#readme
license: other
licenses:
- sources: LICENSE
text: |-
MIT License
Copyright (c) 2023 The Fastify Team
The Fastify team members are listed at https://github.com/fastify/fastify#team
and in the README file.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- sources: README.md
text: Licensed under [MIT](./LICENSE).
notices: []
+33
View File
@@ -0,0 +1,33 @@
---
name: json-with-bigint
version: 3.5.3
type: npm
summary: JS library that allows you to easily serialize and deserialize data with
BigInt values
homepage:
license: mit
licenses:
- sources: LICENSE
text: |
MIT License
Copyright (c) 2023 Ivan Korolenko
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
notices: []
+66
View File
@@ -0,0 +1,66 @@
---
name: minimatch
version: 9.0.8
type: npm
summary:
homepage:
license: blueoak-1.0.0
licenses:
- sources: LICENSE.md
text: |
# Blue Oak Model License
Version 1.0.0
## Purpose
This license gives everyone as much permission to work with
this software as possible, while protecting contributors
from liability.
## Acceptance
In order to receive this license, you must agree to its
rules. The rules of this license are both obligations
under that agreement and conditions to your license.
You must not do anything with this software that triggers
a rule that you cannot or will not follow.
## Copyright
Each contributor licenses you to do everything with this
software that would otherwise infringe that contributor's
copyright in it.
## Notices
You must ensure that everyone who gets a copy of
any part of this software from you, with or without
changes, also gets the text of this license or a link to
<https://blueoakcouncil.org/license/1.0.0>.
## Excuse
If anyone notifies you in writing that you have not
complied with [Notices](#notices), you can keep your
license by taking all practical steps to comply within 30
days after the notice. If you do not do so, your license
ends immediately.
## Patent
Each contributor licenses you to do everything with this
software that would otherwise infringe any patent claims
they can license or become able to license.
## Reliability
No contributor can revoke this license.
## No Liability
**_As far as the law allows, this software comes as is,
without any warranty or condition, and no contributor
will be liable to anyone for any damages related to this
software or this license, under any kind of legal claim._**
notices: []
+2 -2
View File
@@ -1,8 +1,8 @@
---
name: minimatch
version: 10.2.4
version: 10.1.1
type: npm
summary:
summary: a glob matcher in javascript
homepage:
license: blueoak-1.0.0
licenses:
+73 -52
View File
@@ -11,14 +11,15 @@ Upload [Actions Artifacts](https://docs.github.com/en/actions/using-workflows/st
See also [download-artifact](https://github.com/actions/download-artifact).
- [`@actions/upload-artifact`](#actionsupload-artifact)
- [What's new](#whats-new)
- [GHES Support](#ghes-support)
- [v6 - What's new](#v6---whats-new)
- [v4 - What's new](#v4---whats-new)
- [Improvements](#improvements)
- [Breaking Changes](#breaking-changes)
- [Usage](#usage)
- [Inputs](#inputs)
- [Outputs](#outputs)
- [Examples](#examples)
- [Upload an Individual File (Zipped)](#upload-an-individual-file-zipped)
- [Upload an Individual File (Unzipped)](#upload-an-individual-file-unzipped)
- [Upload an Individual File](#upload-an-individual-file)
- [Upload an Entire Directory](#upload-an-entire-directory)
- [Upload using a Wildcard Pattern](#upload-using-a-wildcard-pattern)
- [Upload using Multiple Paths and Exclusions](#upload-using-multiple-paths-and-exclusions)
@@ -33,12 +34,49 @@ See also [download-artifact](https://github.com/actions/download-artifact).
- [Overwriting an Artifact](#overwriting-an-artifact)
- [Limitations](#limitations)
- [Number of Artifacts](#number-of-artifacts)
- [Zip archives](#zip-archives)
- [Permission Loss](#permission-loss)
- [Where does the upload go?](#where-does-the-upload-go)
## What's new
Check out the [releases page](https://github.com/actions/upload-artifact/releases) for details on what's new.
## v6 - What's new
> [!IMPORTANT]
> actions/upload-artifact@v6 now runs on Node.js 24 (`runs.using: node24`) and requires a minimum Actions Runner version of 2.327.1. If you are using self-hosted runners, ensure they are updated before upgrading.
### Node.js 24
This release updates the runtime to Node.js 24. v5 had preliminary support for Node.js 24, however this action was by default still running on Node.js 20. Now this action by default will run on Node.js 24.
## v4 - What's new
> [!IMPORTANT]
> upload-artifact@v4+ is not currently supported on GitHub Enterprise Server (GHES) yet. If you are on GHES, you must use [v3](https://github.com/actions/upload-artifact/releases/tag/v3) (Node 16) or [v3-node20](https://github.com/actions/upload-artifact/releases/tag/v3-node20) (Node 20).
The release of upload-artifact@v4 and download-artifact@v4 are major changes to the backend architecture of Artifacts. They have numerous performance and behavioral improvements.
For more information, see the [`@actions/artifact`](https://github.com/actions/toolkit/tree/main/packages/artifact) documentation.
There is also a new sub-action, `actions/upload-artifact/merge`. For more info, check out that action's [README](./merge/README.md).
### Improvements
1. Uploads are significantly faster, upwards of 90% improvement in worst case scenarios.
2. Once uploaded, an Artifact ID is returned and Artifacts are immediately available in the UI and [REST API](https://docs.github.com/en/rest/actions/artifacts). Previously, you would have to wait for the run to be completed before an ID was available or any APIs could be utilized.
3. The contents of an Artifact are uploaded together into an _immutable_ archive. They cannot be altered by subsequent jobs unless the Artifacts are deleted and recreated (where they will have a new ID). Both of these factors help reduce the possibility of accidentally corrupting Artifact files.
4. The compression level of an Artifact can be manually tweaked for speed or size reduction.
### Breaking Changes
1. On self hosted runners, additional [firewall rules](https://github.com/actions/toolkit/tree/main/packages/artifact#breaking-changes) may be required.
2. Uploading to the same named Artifact multiple times.
Due to how Artifacts are created in this new version, it is no longer possible to upload to the same named Artifact multiple times. You must either split the uploads into multiple Artifacts with different names, or only upload once. Otherwise you _will_ encounter an error.
3. Limit of Artifacts for an individual job. Each job in a workflow run now has a limit of 500 artifacts.
4. With `v4.4` and later, hidden files are excluded by default.
For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
## Note
@@ -58,16 +96,12 @@ We will still provide security updates for this project and fix major breaking c
You are welcome to still raise bugs in this repo.
## GHES Support
`upload-artifact@v4+` is not currently supported on GitHub Enterprise Server (GHES). If you are on GHES, you must use [v3](https://github.com/actions/upload-artifact/releases?q=v3) (Node v20). We will also provide releases for specific NodeJS versions. For example: [v3.2.2-node24](https://github.com/actions/upload-artifact/releases/tag/v3.2.2-node20) runs `v3.2.2` on NodeJS v24 (see the releases page for all supported Node versions).
## Usage
### Inputs
```yaml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
# Name of the artifact to upload.
# Optional. Default is 'artifact'
@@ -108,11 +142,6 @@ You are welcome to still raise bugs in this repo.
# enabled this to avoid uploading sensitive information.
# Optional. Default is 'false'
include-hidden-files:
# Whether to zip the artifact files before upload
# If 'false', only a single file can be uploaded. The name of the file will be used as the artifact name (the 'name' parameter is ignored)
# Optional. Default is 'true'
archive:
```
### Outputs
@@ -125,34 +154,22 @@ You are welcome to still raise bugs in this repo.
## Examples
### Upload an Individual File (Zipped)
### Upload an Individual File
```yaml
steps:
- run: mkdir -p path/to/artifact
- run: echo hello > path/to/artifact/world.txt
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: path/to/artifact/world.txt
```
### Upload an Individual File (Unzipped)
```yaml
steps:
- run: mkdir -p path/to/artifact
- run: echo hello > path/to/artifact/world.txt
- uses: actions/upload-artifact@v7
with:
path: path/to/artifact/world.txt
archive: false
```
### Upload an Entire Directory
```yaml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: path/to/artifact/ # or path/to/artifact
@@ -161,7 +178,7 @@ steps:
### Upload using a Wildcard Pattern
```yaml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: path/**/[abc]rtifac?/*
@@ -170,7 +187,7 @@ steps:
### Upload using Multiple Paths and Exclusions
```yaml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: |
@@ -218,7 +235,7 @@ For instance, if you are uploading random binary data, you can save a lot of tim
- name: Make a 1GB random binary file
run: |
dd if=/dev/urandom of=my-1gb-file bs=1M count=1000
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: my-1gb-file
@@ -231,7 +248,7 @@ But, if you are uploading data that is easily compressed (like plaintext, code,
- name: Make a file with a lot of repeated text
run: |
for i in {1..100000}; do echo -n 'foobar' >> foobar.txt; done
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: foobar.txt
@@ -243,7 +260,7 @@ But, if you are uploading data that is easily compressed (like plaintext, code,
If a path (or paths), result in no files being found for the artifact, the action will succeed but print out a warning. In certain scenarios it may be desirable to fail the action or suppress the warning. The `if-no-files-found` option allows you to customize the behavior of the action if no files are found:
```yaml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
path: path/to/artifact/
@@ -256,13 +273,13 @@ Unlike earlier versions of `upload-artifact`, uploading to the same artifact via
```yaml
- run: echo hi > world.txt
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
# implicitly named as 'artifact'
path: world.txt
- run: echo howdy > extra-file.txt
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
# also implicitly named as 'artifact', will fail here!
path: extra-file.txt
@@ -288,7 +305,7 @@ jobs:
- name: Build
run: ./some-script --version=${{ matrix.version }} > my-binary
- name: Upload
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: binary-${{ matrix.os }}-${{ matrix.version }}
path: my-binary
@@ -306,7 +323,7 @@ You can use `~` in the path input as a substitute for `$HOME`. Basic tilde expan
- run: |
mkdir -p ~/new/artifact
echo hello > ~/new/artifact/world.txt
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifacts
path: ~/new/**/*
@@ -321,7 +338,7 @@ Environment variables along with context expressions can also be used for input.
- run: |
mkdir -p ${{ github.workspace }}/artifact
echo hello > ${{ github.workspace }}/artifact/world.txt
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: ${{ env.name }}-name
path: ${{ github.workspace }}/artifact/**/*
@@ -335,7 +352,7 @@ For environment variables created in other steps, make sure to use the `env` exp
mkdir testing
echo "This is a file to upload" > testing/file.txt
echo "artifactPath=testing/file.txt" >> $GITHUB_ENV
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: artifact
path: ${{ env.artifactPath }} # this will resolve to testing/file.txt at runtime
@@ -350,7 +367,7 @@ Artifacts are retained for 90 days by default. You can specify a shorter retenti
run: echo "I won't live long" > my_file.txt
- name: Upload Artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: my-artifact
path: my_file.txt
@@ -366,7 +383,7 @@ If an artifact upload is successful then an `artifact-id` output is available. T
#### Example output between steps
```yml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: my-artifact
@@ -385,7 +402,7 @@ jobs:
outputs:
output1: ${{ steps.artifact-upload-step.outputs.artifact-id }}
steps:
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
id: artifact-upload-step
with:
name: my-artifact
@@ -411,7 +428,7 @@ jobs:
- name: Create a file
run: echo "hello world" > my-file.txt
- name: Upload Artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: my-artifact # NOTE: same artifact name
path: my-file.txt
@@ -422,7 +439,7 @@ jobs:
- name: Create a different file
run: echo "goodbye world" > my-file.txt
- name: Upload Artifact
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: my-artifact # NOTE: same artifact name
path: my-file.txt
@@ -438,7 +455,7 @@ Any files that contain sensitive information that should not be in the uploaded
using the `path`:
```yaml
- uses: actions/upload-artifact@v7
- uses: actions/upload-artifact@v4
with:
name: my-artifact
include-hidden-files: true
@@ -459,21 +476,25 @@ Within an individual job, there is a limit of 500 artifacts that can be created
You may also be limited by Artifacts if you have exceeded your shared storage quota. Storage is calculated every 6-12 hours. See [the documentation](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#calculating-minute-and-storage-spending) for more info.
### Zip archives
When an Artifact is uploaded, all the files are assembled into an immutable Zip archive. There is currently no way to download artifacts in a format other than a Zip or to download individual artifact contents.
### Permission Loss
File permissions are not maintained during zipped artifact upload. All directories will have `755` and all files will have `644`. For example, if you make a file executable using `chmod` and then upload that file with `archive: true`, post-download the file is no longer guaranteed to be set as an executable.
File permissions are not maintained during artifact upload. All directories will have `755` and all files will have `644`. For example, if you make a file executable using `chmod` and then upload that file, post-download the file is no longer guaranteed to be set as an executable.
If you must preserve permissions, you can `tar` all of your files together before artifact upload and upload that file directly with `archive: false`. Post download, the `tar` file will maintain file permissions and case sensitivity.
If you must preserve permissions, you can `tar` all of your files together before artifact upload. Post download, the `tar` file will maintain file permissions and case sensitivity.
```yaml
- name: 'Tar files'
run: tar -cvf my_files.tar /path/to/my/directory
- name: 'Upload Artifact'
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@v4
with:
name: my-artifact
path: my_files.tar
archive: false
```
## Where does the upload go?
-54
View File
@@ -72,7 +72,6 @@ const mockInputs = (
[Inputs.RetentionDays]: 0,
[Inputs.CompressionLevel]: 6,
[Inputs.Overwrite]: false,
[Inputs.Archive]: true,
...overrides
}
@@ -274,57 +273,4 @@ describe('upload', () => {
`Skipping deletion of '${fixtures.artifactName}', it does not exist`
)
})
test('passes skipArchive when archive is false', async () => {
mockInputs({
[Inputs.Archive]: false
})
mockFindFilesToUpload.mockResolvedValue({
filesToUpload: [fixtures.filesToUpload[0]],
rootDirectory: fixtures.rootDirectory
})
await run()
expect(artifact.default.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
[fixtures.filesToUpload[0]],
fixtures.rootDirectory,
{compressionLevel: 6, skipArchive: true}
)
})
test('does not pass skipArchive when archive is true', async () => {
mockInputs({
[Inputs.Archive]: true
})
mockFindFilesToUpload.mockResolvedValue({
filesToUpload: [fixtures.filesToUpload[0]],
rootDirectory: fixtures.rootDirectory
})
await run()
expect(artifact.default.uploadArtifact).toHaveBeenCalledWith(
fixtures.artifactName,
[fixtures.filesToUpload[0]],
fixtures.rootDirectory,
{compressionLevel: 6}
)
})
test('fails when archive is false and multiple files are provided', async () => {
mockInputs({
[Inputs.Archive]: false
})
await run()
expect(core.setFailed).toHaveBeenCalledWith(
`When 'archive' is set to false, only a single file can be uploaded. Found ${fixtures.filesToUpload.length} files to upload.`
)
expect(artifact.default.uploadArtifact).not.toHaveBeenCalled()
})
})
+2 -8
View File
@@ -3,10 +3,10 @@ description: 'Upload a build artifact that can be used by subsequent workflow st
author: 'GitHub'
inputs:
name:
description: 'Artifact name. If the `archive` input is `false`, the name of the file uploaded will be the artifact name.'
description: 'Artifact name'
default: 'artifact'
path:
description: 'A file, directory or wildcard pattern that describes what to upload.'
description: 'A file, directory or wildcard pattern that describes what to upload'
required: true
if-no-files-found:
description: >
@@ -45,12 +45,6 @@ inputs:
If true, hidden files will be included in the artifact.
If false, hidden files will be excluded from the artifact.
default: 'false'
archive:
description: >
If true, the artifact will be archived (zipped) before uploading.
If false, the artifact will be uploaded as-is without archiving.
When `archive` is `false`, only a single file can be uploaded. The name of the file will be used as the artifact name (ignoring the `name` parameter).
default: 'true'
outputs:
artifact-id:
+80 -100
View File
@@ -88021,13 +88021,13 @@ class Sanitizer {
message: value.message,
};
}
if (key === "headers" && isObject(value)) {
if (key === "headers") {
return this.sanitizeHeaders(value);
}
else if (key === "url" && typeof value === "string") {
else if (key === "url") {
return this.sanitizeUrl(value);
}
else if (key === "query" && isObject(value)) {
else if (key === "query") {
return this.sanitizeQuery(value);
}
else if (key === "body") {
@@ -88598,68 +88598,6 @@ function logPolicy_logPolicy(options = {}) {
};
}
//# sourceMappingURL=logPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/redirectPolicy.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* The programmatic identifier of the redirectPolicy.
*/
const redirectPolicyName = "redirectPolicy";
/**
* Methods that are allowed to follow redirects 301 and 302
*/
const allowedRedirect = ["GET", "HEAD"];
/**
* A policy to follow Location headers from the server in order
* to support server-side redirection.
* In the browser, this policy is not used.
* @param options - Options to control policy behavior.
*/
function redirectPolicy_redirectPolicy(options = {}) {
const { maxRetries = 20, allowCrossOriginRedirects = false } = options;
return {
name: redirectPolicyName,
async sendRequest(request, next) {
const response = await next(request);
return handleRedirect(next, response, maxRetries, allowCrossOriginRedirects);
},
};
}
async function handleRedirect(next, response, maxRetries, allowCrossOriginRedirects, currentRetries = 0) {
const { request, status, headers } = response;
const locationHeader = headers.get("location");
if (locationHeader &&
(status === 300 ||
(status === 301 && allowedRedirect.includes(request.method)) ||
(status === 302 && allowedRedirect.includes(request.method)) ||
(status === 303 && request.method === "POST") ||
status === 307) &&
currentRetries < maxRetries) {
const url = new URL(locationHeader, request.url);
// Only follow redirects to the same origin by default.
if (!allowCrossOriginRedirects) {
const originalUrl = new URL(request.url);
if (url.origin !== originalUrl.origin) {
log_logger.verbose(`Skipping cross-origin redirect from ${originalUrl.origin} to ${url.origin}.`);
return response;
}
}
request.url = url.toString();
// POST request with Status code 303 should be converted into a
// redirected GET request if the redirect url is present in the location header
if (status === 303) {
request.method = "GET";
request.headers.delete("Content-Length");
delete request.body;
}
request.headers.delete("Authorization");
const res = await next(request);
return handleRedirect(next, res, maxRetries, allowCrossOriginRedirects, currentRetries + 1);
}
return response;
}
//# sourceMappingURL=redirectPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/util/userAgentPlatform.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
@@ -88677,14 +88615,15 @@ function getHeaderName() {
async function userAgentPlatform_setPlatformSpecificData(map) {
if (process && process.versions) {
const osInfo = `${os.type()} ${os.release()}; ${os.arch()}`;
if (process.versions.bun) {
map.set("Bun", `${process.versions.bun} (${osInfo})`);
const versions = process.versions;
if (versions.bun) {
map.set("Bun", `${versions.bun} (${osInfo})`);
}
else if (process.versions.deno) {
map.set("Deno", `${process.versions.deno} (${osInfo})`);
else if (versions.deno) {
map.set("Deno", `${versions.deno} (${osInfo})`);
}
else if (process.versions.node) {
map.set("Node", `${process.versions.node} (${osInfo})`);
else if (versions.node) {
map.set("Node", `${versions.node} (${osInfo})`);
}
}
}
@@ -88991,7 +88930,7 @@ function isSystemError(err) {
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/constants.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
const constants_SDK_VERSION = "0.3.5";
const constants_SDK_VERSION = "0.3.3";
const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
//# sourceMappingURL=constants.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/retryPolicy.js
@@ -89001,7 +88940,6 @@ const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
const retryPolicyLogger = createClientLogger("ts-http-runtime retryPolicy");
/**
* The programmatic identifier of the retryPolicy.
@@ -89032,11 +88970,11 @@ function retryPolicy_retryPolicy(strategies, options = { maxRetries: constants_D
// RestErrors are valid targets for the retry strategies.
// If none of the retry strategies can work with them, they will be thrown later in this policy.
// If the received error is not a RestError, it is immediately thrown.
if (!restError_isRestError(e)) {
responseError = e;
if (!e || responseError.name !== "RestError") {
throw e;
}
responseError = e;
response = e.response;
response = responseError.response;
}
if (request.abortSignal?.aborted) {
logger.error(`Retry ${retryCount}: Request aborted.`);
@@ -89437,15 +89375,16 @@ function setProxyAgentOnRequest(request, cachedAgents, proxyUrl) {
if (request.tlsSettings) {
log_logger.warning("TLS settings are not supported in combination with custom Proxy, certificates provided to the client will be ignored.");
}
const headers = request.headers.toJSON();
if (isInsecure) {
if (!cachedAgents.httpProxyAgent) {
cachedAgents.httpProxyAgent = new http_proxy_agent_dist.HttpProxyAgent(proxyUrl);
cachedAgents.httpProxyAgent = new http_proxy_agent_dist.HttpProxyAgent(proxyUrl, { headers });
}
request.agent = cachedAgents.httpProxyAgent;
}
else {
if (!cachedAgents.httpsProxyAgent) {
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl);
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl, { headers });
}
request.agent = cachedAgents.httpsProxyAgent;
}
@@ -89497,13 +89436,13 @@ function typeGuards_isBinaryBody(body) {
(body instanceof Uint8Array ||
typeGuards_isReadableStream(body) ||
typeof body === "function" ||
(typeof Blob !== "undefined" && body instanceof Blob)));
body instanceof Blob));
}
function typeGuards_isReadableStream(x) {
return isNodeReadableStream(x) || isWebReadableStream(x);
}
function typeGuards_isBlob(x) {
return typeof Blob !== "undefined" && x instanceof Blob;
function isBlob(x) {
return typeof x.stream === "function";
}
//# sourceMappingURL=typeGuards.js.map
// EXTERNAL MODULE: external "stream"
@@ -89549,7 +89488,7 @@ function toStream(source) {
if (source instanceof Uint8Array) {
return external_stream_.Readable.from(Buffer.from(source));
}
else if (typeGuards_isBlob(source)) {
else if (isBlob(source)) {
return ensureNodeStream(source.stream());
}
else {
@@ -89599,7 +89538,7 @@ function getLength(source) {
if (source instanceof Uint8Array) {
return source.byteLength;
}
else if (typeGuards_isBlob(source)) {
else if (isBlob(source)) {
// if was created using createFile then -1 means we have an unknown size
return source.size === -1 ? undefined : source.size;
}
@@ -90128,14 +90067,9 @@ async function sendRequest_sendRequest(method, url, pipeline, options = {}, cust
* @returns returns the content-type
*/
function getRequestContentType(options = {}) {
if (options.contentType) {
return options.contentType;
}
const headerContentType = options.headers?.["content-type"];
if (typeof headerContentType === "string") {
return headerContentType;
}
return getContentType(options.body);
return (options.contentType ??
options.headers?.["content-type"] ??
getContentType(options.body));
}
/**
* Function to determine the content-type of a body
@@ -90150,9 +90084,6 @@ function getContentType(body) {
if (ArrayBuffer.isView(body)) {
return "application/octet-stream";
}
if (isBlob(body) && body.type) {
return body.type;
}
if (typeof body === "string") {
try {
JSON.parse(body);
@@ -90203,15 +90134,9 @@ function getRequestBody(body, contentType = "") {
if (typeof FormData !== "undefined" && body instanceof FormData) {
return { body };
}
if (isBlob(body)) {
return { body };
}
if (isReadableStream(body)) {
return { body };
}
if (typeof body === "function") {
return { body: body };
}
if (ArrayBuffer.isView(body)) {
return { body: body instanceof Uint8Array ? body : JSON.stringify(body) };
}
@@ -90401,6 +90326,8 @@ function statusCodeToNumber(statusCode) {
//# sourceMappingURL=index.js.map
;// CONCATENATED MODULE: ./node_modules/@azure/core-rest-pipeline/dist/esm/pipeline.js
// Copyright (c) Microsoft Corporation.
@@ -90597,6 +90524,59 @@ function throttlingRetryPolicy(options = {}) {
};
}
//# sourceMappingURL=throttlingRetryPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/redirectPolicy.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* The programmatic identifier of the redirectPolicy.
*/
const redirectPolicyName = "redirectPolicy";
/**
* Methods that are allowed to follow redirects 301 and 302
*/
const allowedRedirect = ["GET", "HEAD"];
/**
* A policy to follow Location headers from the server in order
* to support server-side redirection.
* In the browser, this policy is not used.
* @param options - Options to control policy behavior.
*/
function redirectPolicy_redirectPolicy(options = {}) {
const { maxRetries = 20 } = options;
return {
name: redirectPolicyName,
async sendRequest(request, next) {
const response = await next(request);
return handleRedirect(next, response, maxRetries);
},
};
}
async function handleRedirect(next, response, maxRetries, currentRetries = 0) {
const { request, status, headers } = response;
const locationHeader = headers.get("location");
if (locationHeader &&
(status === 300 ||
(status === 301 && allowedRedirect.includes(request.method)) ||
(status === 302 && allowedRedirect.includes(request.method)) ||
(status === 303 && request.method === "POST") ||
status === 307) &&
currentRetries < maxRetries) {
const url = new URL(locationHeader, request.url);
request.url = url.toString();
// POST request with Status code 303 should be converted into a
// redirected GET request if the redirect url is present in the location header
if (status === 303) {
request.method = "GET";
request.headers.delete("Content-Length");
delete request.body;
}
request.headers.delete("Authorization");
const res = await next(request);
return handleRedirect(next, res, maxRetries, currentRetries + 1);
}
return response;
}
//# sourceMappingURL=redirectPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/tlsPolicy.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
+81 -112
View File
@@ -85596,13 +85596,13 @@ class Sanitizer {
message: value.message,
};
}
if (key === "headers" && isObject(value)) {
if (key === "headers") {
return this.sanitizeHeaders(value);
}
else if (key === "url" && typeof value === "string") {
else if (key === "url") {
return this.sanitizeUrl(value);
}
else if (key === "query" && isObject(value)) {
else if (key === "query") {
return this.sanitizeQuery(value);
}
else if (key === "body") {
@@ -86173,68 +86173,6 @@ function logPolicy_logPolicy(options = {}) {
};
}
//# sourceMappingURL=logPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/redirectPolicy.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* The programmatic identifier of the redirectPolicy.
*/
const redirectPolicyName = "redirectPolicy";
/**
* Methods that are allowed to follow redirects 301 and 302
*/
const allowedRedirect = ["GET", "HEAD"];
/**
* A policy to follow Location headers from the server in order
* to support server-side redirection.
* In the browser, this policy is not used.
* @param options - Options to control policy behavior.
*/
function redirectPolicy_redirectPolicy(options = {}) {
const { maxRetries = 20, allowCrossOriginRedirects = false } = options;
return {
name: redirectPolicyName,
async sendRequest(request, next) {
const response = await next(request);
return handleRedirect(next, response, maxRetries, allowCrossOriginRedirects);
},
};
}
async function handleRedirect(next, response, maxRetries, allowCrossOriginRedirects, currentRetries = 0) {
const { request, status, headers } = response;
const locationHeader = headers.get("location");
if (locationHeader &&
(status === 300 ||
(status === 301 && allowedRedirect.includes(request.method)) ||
(status === 302 && allowedRedirect.includes(request.method)) ||
(status === 303 && request.method === "POST") ||
status === 307) &&
currentRetries < maxRetries) {
const url = new URL(locationHeader, request.url);
// Only follow redirects to the same origin by default.
if (!allowCrossOriginRedirects) {
const originalUrl = new URL(request.url);
if (url.origin !== originalUrl.origin) {
log_logger.verbose(`Skipping cross-origin redirect from ${originalUrl.origin} to ${url.origin}.`);
return response;
}
}
request.url = url.toString();
// POST request with Status code 303 should be converted into a
// redirected GET request if the redirect url is present in the location header
if (status === 303) {
request.method = "GET";
request.headers.delete("Content-Length");
delete request.body;
}
request.headers.delete("Authorization");
const res = await next(request);
return handleRedirect(next, res, maxRetries, allowCrossOriginRedirects, currentRetries + 1);
}
return response;
}
//# sourceMappingURL=redirectPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/util/userAgentPlatform.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
@@ -86252,14 +86190,15 @@ function getHeaderName() {
async function userAgentPlatform_setPlatformSpecificData(map) {
if (process && process.versions) {
const osInfo = `${os.type()} ${os.release()}; ${os.arch()}`;
if (process.versions.bun) {
map.set("Bun", `${process.versions.bun} (${osInfo})`);
const versions = process.versions;
if (versions.bun) {
map.set("Bun", `${versions.bun} (${osInfo})`);
}
else if (process.versions.deno) {
map.set("Deno", `${process.versions.deno} (${osInfo})`);
else if (versions.deno) {
map.set("Deno", `${versions.deno} (${osInfo})`);
}
else if (process.versions.node) {
map.set("Node", `${process.versions.node} (${osInfo})`);
else if (versions.node) {
map.set("Node", `${versions.node} (${osInfo})`);
}
}
}
@@ -86566,7 +86505,7 @@ function isSystemError(err) {
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/constants.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
const constants_SDK_VERSION = "0.3.5";
const constants_SDK_VERSION = "0.3.3";
const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
//# sourceMappingURL=constants.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/retryPolicy.js
@@ -86576,7 +86515,6 @@ const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
const retryPolicyLogger = createClientLogger("ts-http-runtime retryPolicy");
/**
* The programmatic identifier of the retryPolicy.
@@ -86607,11 +86545,11 @@ function retryPolicy_retryPolicy(strategies, options = { maxRetries: constants_D
// RestErrors are valid targets for the retry strategies.
// If none of the retry strategies can work with them, they will be thrown later in this policy.
// If the received error is not a RestError, it is immediately thrown.
if (!restError_isRestError(e)) {
responseError = e;
if (!e || responseError.name !== "RestError") {
throw e;
}
responseError = e;
response = e.response;
response = responseError.response;
}
if (request.abortSignal?.aborted) {
logger.error(`Retry ${retryCount}: Request aborted.`);
@@ -87012,15 +86950,16 @@ function setProxyAgentOnRequest(request, cachedAgents, proxyUrl) {
if (request.tlsSettings) {
log_logger.warning("TLS settings are not supported in combination with custom Proxy, certificates provided to the client will be ignored.");
}
const headers = request.headers.toJSON();
if (isInsecure) {
if (!cachedAgents.httpProxyAgent) {
cachedAgents.httpProxyAgent = new http_proxy_agent_dist.HttpProxyAgent(proxyUrl);
cachedAgents.httpProxyAgent = new http_proxy_agent_dist.HttpProxyAgent(proxyUrl, { headers });
}
request.agent = cachedAgents.httpProxyAgent;
}
else {
if (!cachedAgents.httpsProxyAgent) {
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl);
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl, { headers });
}
request.agent = cachedAgents.httpsProxyAgent;
}
@@ -87072,13 +87011,13 @@ function typeGuards_isBinaryBody(body) {
(body instanceof Uint8Array ||
typeGuards_isReadableStream(body) ||
typeof body === "function" ||
(typeof Blob !== "undefined" && body instanceof Blob)));
body instanceof Blob));
}
function typeGuards_isReadableStream(x) {
return isNodeReadableStream(x) || isWebReadableStream(x);
}
function typeGuards_isBlob(x) {
return typeof Blob !== "undefined" && x instanceof Blob;
function isBlob(x) {
return typeof x.stream === "function";
}
//# sourceMappingURL=typeGuards.js.map
// EXTERNAL MODULE: external "stream"
@@ -87124,7 +87063,7 @@ function toStream(source) {
if (source instanceof Uint8Array) {
return external_stream_.Readable.from(Buffer.from(source));
}
else if (typeGuards_isBlob(source)) {
else if (isBlob(source)) {
return ensureNodeStream(source.stream());
}
else {
@@ -87174,7 +87113,7 @@ function getLength(source) {
if (source instanceof Uint8Array) {
return source.byteLength;
}
else if (typeGuards_isBlob(source)) {
else if (isBlob(source)) {
// if was created using createFile then -1 means we have an unknown size
return source.size === -1 ? undefined : source.size;
}
@@ -87703,14 +87642,9 @@ async function sendRequest_sendRequest(method, url, pipeline, options = {}, cust
* @returns returns the content-type
*/
function getRequestContentType(options = {}) {
if (options.contentType) {
return options.contentType;
}
const headerContentType = options.headers?.["content-type"];
if (typeof headerContentType === "string") {
return headerContentType;
}
return getContentType(options.body);
return (options.contentType ??
options.headers?.["content-type"] ??
getContentType(options.body));
}
/**
* Function to determine the content-type of a body
@@ -87725,9 +87659,6 @@ function getContentType(body) {
if (ArrayBuffer.isView(body)) {
return "application/octet-stream";
}
if (isBlob(body) && body.type) {
return body.type;
}
if (typeof body === "string") {
try {
JSON.parse(body);
@@ -87778,15 +87709,9 @@ function getRequestBody(body, contentType = "") {
if (typeof FormData !== "undefined" && body instanceof FormData) {
return { body };
}
if (isBlob(body)) {
return { body };
}
if (isReadableStream(body)) {
return { body };
}
if (typeof body === "function") {
return { body: body };
}
if (ArrayBuffer.isView(body)) {
return { body: body instanceof Uint8Array ? body : JSON.stringify(body) };
}
@@ -87976,6 +87901,8 @@ function statusCodeToNumber(statusCode) {
//# sourceMappingURL=index.js.map
;// CONCATENATED MODULE: ./node_modules/@azure/core-rest-pipeline/dist/esm/pipeline.js
// Copyright (c) Microsoft Corporation.
@@ -88172,6 +88099,59 @@ function throttlingRetryPolicy(options = {}) {
};
}
//# sourceMappingURL=throttlingRetryPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/redirectPolicy.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* The programmatic identifier of the redirectPolicy.
*/
const redirectPolicyName = "redirectPolicy";
/**
* Methods that are allowed to follow redirects 301 and 302
*/
const allowedRedirect = ["GET", "HEAD"];
/**
* A policy to follow Location headers from the server in order
* to support server-side redirection.
* In the browser, this policy is not used.
* @param options - Options to control policy behavior.
*/
function redirectPolicy_redirectPolicy(options = {}) {
const { maxRetries = 20 } = options;
return {
name: redirectPolicyName,
async sendRequest(request, next) {
const response = await next(request);
return handleRedirect(next, response, maxRetries);
},
};
}
async function handleRedirect(next, response, maxRetries, currentRetries = 0) {
const { request, status, headers } = response;
const locationHeader = headers.get("location");
if (locationHeader &&
(status === 300 ||
(status === 301 && allowedRedirect.includes(request.method)) ||
(status === 302 && allowedRedirect.includes(request.method)) ||
(status === 303 && request.method === "POST") ||
status === 307) &&
currentRetries < maxRetries) {
const url = new URL(locationHeader, request.url);
request.url = url.toString();
// POST request with Status code 303 should be converted into a
// redirected GET request if the redirect url is present in the location header
if (status === 303) {
request.method = "GET";
request.headers.delete("Content-Length");
delete request.body;
}
request.headers.delete("Authorization");
const res = await next(request);
return handleRedirect(next, res, maxRetries, currentRetries + 1);
}
return response;
}
//# sourceMappingURL=redirectPolicy.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/tlsPolicy.js
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
@@ -130477,7 +130457,6 @@ var Inputs;
Inputs["CompressionLevel"] = "compression-level";
Inputs["Overwrite"] = "overwrite";
Inputs["IncludeHiddenFiles"] = "include-hidden-files";
Inputs["Archive"] = "archive";
})(Inputs || (Inputs = {}));
var NoFileOptions;
(function (NoFileOptions) {
@@ -130506,7 +130485,6 @@ function getInputs() {
const path = getInput(Inputs.Path, { required: true });
const overwrite = getBooleanInput(Inputs.Overwrite);
const includeHiddenFiles = getBooleanInput(Inputs.IncludeHiddenFiles);
const archive = getBooleanInput(Inputs.Archive);
const ifNoFilesFound = getInput(Inputs.IfNoFilesFound);
const noFileBehavior = NoFileOptions[ifNoFilesFound];
if (!noFileBehavior) {
@@ -130517,8 +130495,7 @@ function getInputs() {
searchPath: path,
ifNoFilesFound: noFileBehavior,
overwrite: overwrite,
includeHiddenFiles: includeHiddenFiles,
archive: archive
includeHiddenFiles: includeHiddenFiles
};
const retentionDaysStr = getInput(Inputs.RetentionDays);
if (retentionDaysStr) {
@@ -130599,11 +130576,6 @@ async function run() {
const s = searchResult.filesToUpload.length === 1 ? '' : 's';
info(`With the provided path, there will be ${searchResult.filesToUpload.length} file${s} uploaded`);
core_debug(`Root artifact directory is ${searchResult.rootDirectory}`);
// Validate that only a single file is uploaded when archive is false
if (!inputs.archive && searchResult.filesToUpload.length > 1) {
setFailed(`When 'archive' is set to false, only a single file can be uploaded. Found ${searchResult.filesToUpload.length} files to upload.`);
return;
}
if (inputs.overwrite) {
await deleteArtifactIfExists(inputs.artifactName);
}
@@ -130614,9 +130586,6 @@ async function run() {
if (typeof inputs.compressionLevel !== 'undefined') {
options.compressionLevel = inputs.compressionLevel;
}
if (!inputs.archive) {
options.skipArchive = true;
}
await upload_artifact_uploadArtifact(inputs.artifactName, searchResult.filesToUpload, searchResult.rootDirectory, options);
}
}
+6 -6
View File
@@ -1,15 +1,15 @@
{
"name": "upload-artifact",
"version": "7.0.1",
"version": "7.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "upload-artifact",
"version": "7.0.1",
"version": "7.0.0",
"license": "MIT",
"dependencies": {
"@actions/artifact": "^6.2.0",
"@actions/artifact": "^6.1.0",
"@actions/core": "^3.0.0",
"@actions/github": "^9.0.0",
"@actions/glob": "^0.6.1",
@@ -2477,9 +2477,9 @@
}
},
"node_modules/@typespec/ts-http-runtime": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.5.tgz",
"integrity": "sha512-yURCknZhvywvQItHMMmFSo+fq5arCUIyz/CVk7jD89MSai7dkaX8ufjCWp3NttLojoTVbcE72ri+be/TnEbMHw==",
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@typespec/ts-http-runtime/-/ts-http-runtime-0.3.3.tgz",
"integrity": "sha512-91fp6CAAJSRtH5ja95T1FHSKa8aPW9/Zw6cta81jlZTUw/+Vq8jM/AfF/14h2b71wwR84JUTW/3Y8QPhDAawFA==",
"license": "MIT",
"dependencies": {
"http-proxy-agent": "^7.0.0",
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "upload-artifact",
"version": "7.0.1",
"version": "7.0.0",
"description": "Upload an Actions Artifact in a workflow run",
"type": "module",
"main": "dist/upload/index.js",
@@ -33,7 +33,7 @@
"node": ">=24"
},
"dependencies": {
"@actions/artifact": "^6.2.0",
"@actions/artifact": "^6.1.0",
"@actions/core": "^3.0.0",
"@actions/github": "^9.0.0",
"@actions/glob": "^0.6.1",
+1 -2
View File
@@ -6,8 +6,7 @@ export enum Inputs {
RetentionDays = 'retention-days',
CompressionLevel = 'compression-level',
Overwrite = 'overwrite',
IncludeHiddenFiles = 'include-hidden-files',
Archive = 'archive'
IncludeHiddenFiles = 'include-hidden-files'
}
export enum NoFileOptions {
+1 -3
View File
@@ -10,7 +10,6 @@ export function getInputs(): UploadInputs {
const path = core.getInput(Inputs.Path, {required: true})
const overwrite = core.getBooleanInput(Inputs.Overwrite)
const includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)
const archive = core.getBooleanInput(Inputs.Archive)
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
@@ -30,8 +29,7 @@ export function getInputs(): UploadInputs {
searchPath: path,
ifNoFilesFound: noFileBehavior,
overwrite: overwrite,
includeHiddenFiles: includeHiddenFiles,
archive: archive
includeHiddenFiles: includeHiddenFiles
} as UploadInputs
const retentionDaysStr = core.getInput(Inputs.RetentionDays)
-12
View File
@@ -57,14 +57,6 @@ export async function run(): Promise<void> {
)
core.debug(`Root artifact directory is ${searchResult.rootDirectory}`)
// Validate that only a single file is uploaded when archive is false
if (!inputs.archive && searchResult.filesToUpload.length > 1) {
core.setFailed(
`When 'archive' is set to false, only a single file can be uploaded. Found ${searchResult.filesToUpload.length} files to upload.`
)
return
}
if (inputs.overwrite) {
await deleteArtifactIfExists(inputs.artifactName)
}
@@ -78,10 +70,6 @@ export async function run(): Promise<void> {
options.compressionLevel = inputs.compressionLevel
}
if (!inputs.archive) {
options.skipArchive = true
}
await uploadArtifact(
inputs.artifactName,
searchResult.filesToUpload,
-6
View File
@@ -35,10 +35,4 @@ export interface UploadInputs {
* Whether or not to include hidden files in the artifact
*/
includeHiddenFiles: boolean
/**
* Whether or not to archive (zip) the artifact before uploading.
* When false, only a single file can be uploaded.
*/
archive: boolean
}