Compare commits

..

12 Commits

Author SHA1 Message Date
claude-ceo-assistant 4b83d4b229 chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:12 +00:00
claude-ceo-assistant cb7287dd3a chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:12 +00:00
claude-ceo-assistant 596d5a0c6b chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:11 +00:00
claude-ceo-assistant f7aa3795e8 chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:11 +00:00
claude-ceo-assistant e892e37d4a chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:10 +00:00
claude-ceo-assistant 084fd67814 chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:10 +00:00
claude-ceo-assistant 2f122edadd chore: remove upstream CI workflows (mirror inertization per internal#233) 2026-05-10 14:28:09 +00:00
Yang Cao 043fb46d1a Merge pull request #797 from actions/yacaovsnc/update-dependency
Licensed / Check licenses (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 2s
Include changes in typespec/ts-http-runtime 0.3.5
2026-04-10 12:08:32 -04:00
Yang Cao 634250c138 Include changes in typespec/ts-http-runtime 0.3.5
Code scanning - action / CodeQL-Build (push) Failing after 1s
2026-04-10 11:58:04 -04:00
Daniel Kennedy e454baaac2 Readme: bump all the example versions to v7 (#796) 2026-04-10 10:55:51 -04:00
Daniel Kennedy 74fad66b98 Update the readme with direct upload details (#795)
* Update the readme with direct upload details

* Update the TOC and remove a section

* Fix some wording

* Remove a tautology
2026-04-10 10:49:57 -04:00
Daniel Kennedy bbbca2ddaa Support direct file uploads (#764)
* Cache licenses

* Bump minimatch to 10.1.1

* Try fixing licenced issues

* More licensed fixes

* Support direct file uploads

* Add CI tests for direct uploads

* Use download-artifact@main temporarily

* CI: clean up artifacts on successful runs

* Use script v8

* Fix some issues with the cleanup

* Add unit tests

* Clarify naming
2026-02-25 16:04:27 -05:00
12 changed files with 259 additions and 953 deletions
-53
View File
@@ -1,53 +0,0 @@
# `dist/index.js` is a special file in Actions.
# When you reference an action with `uses:` in a workflow,
# `index.js` is the code that will run.
# For our project, we generate this file through a build process
# from other source files.
# We need to make sure the checked-in `index.js` actually matches what we expect it to be.
name: Check dist/
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:
jobs:
check-dist:
runs-on: ubuntu-latest
steps:
- 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: Rebuild the dist/ directory
run: npm run release
- name: Compare the expected and actual dist/ directories
run: |
if [ "$(git diff --ignore-space-at-eol dist/ | wc -l)" -gt "0" ]; then
echo "Detected uncommitted changes after build. See status below:"
git diff
exit 1
fi
id: diff
# If index.js was different than expected, upload the expected version as an artifact
- uses: actions/upload-artifact@v4
if: ${{ failure() && steps.diff.conclusion == 'failure' }}
with:
name: dist
path: dist/
-46
View File
@@ -1,46 +0,0 @@
name: "Code scanning - action"
on:
push:
branches-ignore: "dependabot/**"
pull_request:
paths-ignore:
- '**.md'
schedule:
- cron: '0 6 * * 3'
jobs:
CodeQL-Build:
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
-24
View File
@@ -1,24 +0,0 @@
name: Licensed
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
name: Check licenses
steps:
- uses: actions/checkout@v4
- run: npm ci
- name: Install licensed
run: |
cd $RUNNER_TEMP
curl -Lfs -o licensed.tar.gz https://github.com/github/licensed/releases/download/2.12.2/licensed-2.12.2-linux-x64.tar.gz
sudo tar -xzf licensed.tar.gz
sudo mv licensed /usr/local/bin/licensed
- run: licensed status
@@ -1,20 +0,0 @@
name: 'Publish Immutable Action Version'
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
packages: write
steps:
- name: Checking out
uses: actions/checkout@v4
- name: Publish
id: publish
uses: actions/publish-immutable-action@0.0.3
@@ -1,28 +0,0 @@
name: Release new action version
on:
release:
types: [released]
workflow_dispatch:
inputs:
TAG_NAME:
description: 'Tag name that the major tag will point to'
required: true
env:
TAG_NAME: ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }}
permissions:
contents: write
jobs:
update_tag:
name: Update the major tag to include the ${{ github.event.inputs.TAG_NAME || github.event.release.tag_name }} changes
environment:
name: releaseNewActionVersion
runs-on: ubuntu-latest
steps:
- name: Update the ${{ env.TAG_NAME }} tag
id: update-major-tag
uses: actions/publish-action@v0.3.0
with:
source-tag: ${{ env.TAG_NAME }}
slack-webhook: ${{ secrets.SLACK_WEBHOOK }}
-114
View File
@@ -1,114 +0,0 @@
name: Test Proxy
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
permissions:
contents: read
jobs:
# End to end upload with proxy
test-proxy-upload:
runs-on: ubuntu-latest
container:
image: ubuntu:latest
options: --cap-add=NET_ADMIN
services:
squid-proxy:
image: ubuntu/squid:latest
ports:
- 3128:3128
env:
http_proxy: http://squid-proxy:3128
https_proxy: http://squid-proxy:3128
steps:
- name: Wait for proxy to be ready
shell: bash
run: |
echo "Waiting for squid proxy to be ready..."
echo "Resolving squid-proxy hostname:"
getent hosts squid-proxy || echo "DNS resolution failed"
for i in $(seq 1 30); do
if (echo > /dev/tcp/squid-proxy/3128) 2>/dev/null; then
echo "Proxy is ready!"
exit 0
fi
echo "Attempt $i: Proxy not ready, waiting..."
sleep 2
done
echo "Proxy failed to become ready"
exit 1
env:
http_proxy: ""
https_proxy: ""
- name: Install dependencies
run: |
apt-get update
apt-get install -y iptables curl
- name: Verify proxy is working
run: |
echo "Testing proxy connectivity..."
curl -s -o /dev/null -w "%{http_code}" --proxy http://squid-proxy:3128 http://github.com || true
echo "Proxy verification complete"
- name: Block direct traffic (enforce proxy usage)
run: |
# Get the squid-proxy container IP
PROXY_IP=$(getent hosts squid-proxy | awk '{ print $1 }')
echo "Proxy IP: $PROXY_IP"
# Allow loopback traffic
iptables -A OUTPUT -o lo -j ACCEPT
# Allow traffic to the proxy container
iptables -A OUTPUT -d $PROXY_IP -j ACCEPT
# Allow established connections
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow DNS (needed for initial resolution)
iptables -A OUTPUT -p udp --dport 53 -j ACCEPT
iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
# Block all other outbound traffic (HTTP/HTTPS)
iptables -A OUTPUT -p tcp --dport 80 -j REJECT
iptables -A OUTPUT -p tcp --dport 443 -j REJECT
# Log the iptables rules for debugging
iptables -L -v -n
- name: Verify direct HTTPS is blocked
run: |
echo "Testing that direct HTTPS requests fail..."
if curl --noproxy '*' -s --connect-timeout 5 https://github.com > /dev/null 2>&1; then
echo "ERROR: Direct HTTPS request succeeded - blocking is not working!"
exit 1
else
echo "SUCCESS: Direct HTTPS request was blocked as expected"
fi
echo "Testing that HTTPS through proxy succeeds..."
if curl --proxy http://squid-proxy:3128 -s --connect-timeout 10 https://github.com > /dev/null 2>&1; then
echo "SUCCESS: HTTPS request through proxy succeeded"
else
echo "ERROR: HTTPS request through proxy failed!"
exit 1
fi
- name: Checkout
uses: actions/checkout@v4
- name: Create artifact file
run: |
mkdir -p test-artifacts
echo "Proxy test artifact - $GITHUB_RUN_ID" > test-artifacts/proxy-test.txt
echo "Random data: $RANDOM $RANDOM $RANDOM" >> test-artifacts/proxy-test.txt
cat test-artifacts/proxy-test.txt
- name: Upload artifact through proxy
uses: ./
with:
name: 'Proxy-Test-Artifact-${{ github.run_id }}'
path: test-artifacts/proxy-test.txt
-428
View File
@@ -1,428 +0,0 @@
name: Test
on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
permissions:
contents: read
actions: write
jobs:
build:
name: Build
strategy:
matrix:
runs-on: [ubuntu-latest, macos-latest, windows-latest]
fail-fast: false
runs-on: ${{ matrix.runs-on }}
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: Lint
run: npm run lint
- name: Format
run: npm run format-check
- name: Test
run: npm run test
# Test end-to-end by uploading a few artifacts and then downloading them
- name: Create artifact files
run: |
mkdir -p path/to/dir-1
mkdir -p path/to/dir-2
mkdir -p path/to/dir-3
mkdir -p symlink/
echo "Lorem ipsum dolor sit amet" > path/to/dir-1/file1.txt
echo "Hello world from file #2" > path/to/dir-2/file2.txt
echo "Hello from a symlinked file" > symlink/original.txt
ln -s $(pwd)/symlink/original.txt symlink/abs.txt
ln -s original.txt symlink/rel.txt
shell: bash
# Upload a single file artifact
- name: 'Upload artifact #1'
uses: ./
with:
name: 'Artifact-A-${{ matrix.runs-on }}'
path: path/to/dir-1/file1.txt
# Upload using a wildcard pattern
- name: 'Upload artifact #2'
uses: ./
with:
name: 'Artifact-Wildcard-${{ matrix.runs-on }}'
path: path/**/dir*/
# Upload a multi-path artifact
- name: 'Upload artifact #3'
uses: ./
with:
name: 'Multi-Path-Artifact-${{ matrix.runs-on }}'
path: |
path/to/dir-1/*
path/to/dir-[23]/*
!path/to/dir-3/*.txt
- name: 'Upload symlinked artifact'
uses: ./
with:
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
path: |
symlink/abs.txt
symlink/rel.txt
# Download Artifact #1 and verify the correctness of the content
- name: 'Download artifact #1'
uses: actions/download-artifact@main
with:
name: 'Artifact-A-${{ matrix.runs-on }}'
path: some/new/path
- name: 'Verify Artifact #1'
run: |
$file = "some/new/path/file1.txt"
if(!(Test-Path -path $file))
{
Write-Error "Expected file does not exist"
}
if(!((Get-Content $file) -ceq "Lorem ipsum dolor sit amet"))
{
Write-Error "File contents of downloaded artifact are incorrect"
}
shell: pwsh
# Download Artifact #2 and verify the correctness of the content
- name: 'Download artifact #2'
uses: actions/download-artifact@main
with:
name: 'Artifact-Wildcard-${{ matrix.runs-on }}'
path: some/other/path
- name: 'Verify Artifact #2'
run: |
$file1 = "some/other/path/to/dir-1/file1.txt"
$file2 = "some/other/path/to/dir-2/file2.txt"
if(!(Test-Path -path $file1) -or !(Test-Path -path $file2))
{
Write-Error "Expected files do not exist"
}
if(!((Get-Content $file1) -ceq "Lorem ipsum dolor sit amet") -or !((Get-Content $file2) -ceq "Hello world from file #2"))
{
Write-Error "File contents of downloaded artifacts are incorrect"
}
shell: pwsh
# Download Artifact #4 and verify the correctness of the content
- name: 'Download artifact #4'
uses: actions/download-artifact@main
with:
name: 'Multi-Path-Artifact-${{ matrix.runs-on }}'
path: multi/artifact
- name: 'Verify Artifact #4'
run: |
$file1 = "multi/artifact/dir-1/file1.txt"
$file2 = "multi/artifact/dir-2/file2.txt"
if(!(Test-Path -path $file1) -or !(Test-Path -path $file2))
{
Write-Error "Expected files do not exist"
}
if(!((Get-Content $file1) -ceq "Lorem ipsum dolor sit amet") -or !((Get-Content $file2) -ceq "Hello world from file #2"))
{
Write-Error "File contents of downloaded artifacts are incorrect"
}
shell: pwsh
- name: 'Download symlinked artifact'
uses: actions/download-artifact@main
with:
name: 'Symlinked-Artifact-${{ matrix.runs-on }}'
path: from/symlink
- name: 'Verify symlinked artifact'
run: |
$abs = "from/symlink/abs.txt"
if(!(Test-Path -path $abs))
{
Write-Error "Expected file does not exist"
}
if(!((Get-Content $abs) -ceq "Hello from a symlinked file"))
{
Write-Error "File contents of downloaded artifact are incorrect"
}
$rel = "from/symlink/rel.txt"
if(!(Test-Path -path $rel))
{
Write-Error "Expected file does not exist"
}
if(!((Get-Content $rel) -ceq "Hello from a symlinked file"))
{
Write-Error "File contents of downloaded artifact are incorrect"
}
shell: pwsh
- name: 'Alter file 1 content'
run: |
echo "This file has changed" > path/to/dir-1/file1.txt
# Replace the contents of Artifact #1
- name: 'Overwrite artifact #1'
uses: ./
with:
name: 'Artifact-A-${{ matrix.runs-on }}'
path: path/to/dir-1/file1.txt
overwrite: true
# Download replaced Artifact #1 and verify the correctness of the content
- name: 'Download artifact #1 again'
uses: actions/download-artifact@main
with:
name: 'Artifact-A-${{ matrix.runs-on }}'
path: overwrite/some/new/path
- name: 'Verify Artifact #1 again'
run: |
$file = "overwrite/some/new/path/file1.txt"
if(!(Test-Path -path $file))
{
Write-Error "Expected file does not exist"
}
if(!((Get-Content $file) -ceq "This file has changed"))
{
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
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
# Merge all artifacts from previous jobs
- name: Merge all artifacts in run
uses: ./merge/
with:
# our matrix produces artifacts with the same file, this prevents "stomping" on each other, also makes it
# easier to identify each of the merged artifacts
separate-directories: true
- name: 'Download merged artifacts'
uses: actions/download-artifact@main
with:
name: merged-artifacts
path: all-merged-artifacts
- name: 'Check merged artifact has directories for each artifact'
run: |
$artifacts = @(
"Artifact-A-ubuntu-latest",
"Artifact-A-macos-latest",
"Artifact-A-windows-latest",
"Artifact-Wildcard-ubuntu-latest",
"Artifact-Wildcard-macos-latest",
"Artifact-Wildcard-windows-latest",
"Multi-Path-Artifact-ubuntu-latest",
"Multi-Path-Artifact-macos-latest",
"Multi-Path-Artifact-windows-latest"
)
foreach ($artifact in $artifacts) {
$path = "all-merged-artifacts/$artifact"
if (!(Test-Path $path)) {
Write-Error "$path does not exist."
}
}
shell: pwsh
# Merge Artifact-A-* from previous jobs
- name: Merge all Artifact-A
uses: ./merge/
with:
name: Merged-Artifact-As
pattern: 'Artifact-A-*'
separate-directories: true
# Download merged artifacts and verify the correctness of the content
- name: 'Download merged artifacts'
uses: actions/download-artifact@main
with:
name: Merged-Artifact-As
path: merged-artifact-a
- name: 'Verify merged artifacts'
run: |
$files = @(
"merged-artifact-a/Artifact-A-ubuntu-latest/file1.txt",
"merged-artifact-a/Artifact-A-macos-latest/file1.txt",
"merged-artifact-a/Artifact-A-windows-latest/file1.txt"
)
foreach ($file in $files) {
if (!(Test-Path $file)) {
Write-Error "$file does not exist."
}
if (!((Get-Content $file) -ceq "This file has changed")) {
Write-Error "$file has incorrect content."
}
}
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}`);
}
}
+53 -74
View File
@@ -11,15 +11,14 @@ 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)
- [v6 - What's new](#v6---whats-new)
- [v4 - What's new](#v4---whats-new)
- [Improvements](#improvements)
- [Breaking Changes](#breaking-changes)
- [What's new](#whats-new)
- [GHES Support](#ghes-support)
- [Usage](#usage)
- [Inputs](#inputs)
- [Outputs](#outputs)
- [Examples](#examples)
- [Upload an Individual File](#upload-an-individual-file)
- [Upload an Individual File (Zipped)](#upload-an-individual-file-zipped)
- [Upload an Individual File (Unzipped)](#upload-an-individual-file-unzipped)
- [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)
@@ -34,53 +33,16 @@ 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
## 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).
Check out the [releases page](https://github.com/actions/upload-artifact/releases) for details on what's new.
## Note
Thank you for your interest in this GitHub repo, however, right now we are not taking contributions.
Thank you for your interest in this GitHub repo, however, right now we are not taking contributions.
We continue to focus our resources on strategic areas that help our customers be successful while making developers' lives easier. While GitHub Actions remains a key part of this vision, we are allocating resources towards other areas of Actions and are not taking contributions to this repository at this time. The GitHub public roadmap is the best place to follow along for any updates on features were working on and what stage theyre in.
@@ -96,12 +58,16 @@ 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.2.2](https://github.com/actions/upload-artifact/releases/tag/v3.2.2) (Node 24) or [v3.2.2-node20](https://github.com/actions/upload-artifact/releases/tag/v3.2.2-node20) (Node 20).
## Usage
### Inputs
```yaml
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
# Name of the artifact to upload.
# Optional. Default is 'artifact'
@@ -142,6 +108,11 @@ 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
@@ -154,22 +125,34 @@ You are welcome to still raise bugs in this repo.
## Examples
### Upload an Individual File
### Upload an Individual File (Zipped)
```yaml
steps:
- run: mkdir -p path/to/artifact
- run: echo hello > path/to/artifact/world.txt
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
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@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
path: path/to/artifact/ # or path/to/artifact
@@ -178,7 +161,7 @@ steps:
### Upload using a Wildcard Pattern
```yaml
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
path: path/**/[abc]rtifac?/*
@@ -187,7 +170,7 @@ steps:
### Upload using Multiple Paths and Exclusions
```yaml
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
path: |
@@ -235,7 +218,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@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
path: my-1gb-file
@@ -248,7 +231,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@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
path: foobar.txt
@@ -260,7 +243,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@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
path: path/to/artifact/
@@ -273,13 +256,13 @@ Unlike earlier versions of `upload-artifact`, uploading to the same artifact via
```yaml
- run: echo hi > world.txt
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
# implicitly named as 'artifact'
path: world.txt
- run: echo howdy > extra-file.txt
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
# also implicitly named as 'artifact', will fail here!
path: extra-file.txt
@@ -305,7 +288,7 @@ jobs:
- name: Build
run: ./some-script --version=${{ matrix.version }} > my-binary
- name: Upload
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: binary-${{ matrix.os }}-${{ matrix.version }}
path: my-binary
@@ -323,7 +306,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@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifacts
path: ~/new/**/*
@@ -338,7 +321,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@v4
- uses: actions/upload-artifact@v7
with:
name: ${{ env.name }}-name
path: ${{ github.workspace }}/artifact/**/*
@@ -352,7 +335,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@v4
- uses: actions/upload-artifact@v7
with:
name: artifact
path: ${{ env.artifactPath }} # this will resolve to testing/file.txt at runtime
@@ -367,7 +350,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@v4
uses: actions/upload-artifact@v7
with:
name: my-artifact
path: my_file.txt
@@ -383,7 +366,7 @@ If an artifact upload is successful then an `artifact-id` output is available. T
#### Example output between steps
```yml
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
id: artifact-upload-step
with:
name: my-artifact
@@ -402,7 +385,7 @@ jobs:
outputs:
output1: ${{ steps.artifact-upload-step.outputs.artifact-id }}
steps:
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
id: artifact-upload-step
with:
name: my-artifact
@@ -428,7 +411,7 @@ jobs:
- name: Create a file
run: echo "hello world" > my-file.txt
- name: Upload Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: my-artifact # NOTE: same artifact name
path: my-file.txt
@@ -439,7 +422,7 @@ jobs:
- name: Create a different file
run: echo "goodbye world" > my-file.txt
- name: Upload Artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: my-artifact # NOTE: same artifact name
path: my-file.txt
@@ -455,7 +438,7 @@ Any files that contain sensitive information that should not be in the uploaded
using the `path`:
```yaml
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v7
with:
name: my-artifact
include-hidden-files: true
@@ -476,25 +459,21 @@ 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 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.
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.
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.
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.
```yaml
- name: 'Tar files'
run: tar -cvf my_files.tar /path/to/my/directory
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: my-artifact
path: my_files.tar
archive: false
```
## Where does the upload go?
+100 -80
View File
@@ -88021,13 +88021,13 @@ class Sanitizer {
message: value.message,
};
}
if (key === "headers") {
if (key === "headers" && isObject(value)) {
return this.sanitizeHeaders(value);
}
else if (key === "url") {
else if (key === "url" && typeof value === "string") {
return this.sanitizeUrl(value);
}
else if (key === "query") {
else if (key === "query" && isObject(value)) {
return this.sanitizeQuery(value);
}
else if (key === "body") {
@@ -88598,6 +88598,68 @@ 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.
@@ -88615,15 +88677,14 @@ function getHeaderName() {
async function userAgentPlatform_setPlatformSpecificData(map) {
if (process && process.versions) {
const osInfo = `${os.type()} ${os.release()}; ${os.arch()}`;
const versions = process.versions;
if (versions.bun) {
map.set("Bun", `${versions.bun} (${osInfo})`);
if (process.versions.bun) {
map.set("Bun", `${process.versions.bun} (${osInfo})`);
}
else if (versions.deno) {
map.set("Deno", `${versions.deno} (${osInfo})`);
else if (process.versions.deno) {
map.set("Deno", `${process.versions.deno} (${osInfo})`);
}
else if (versions.node) {
map.set("Node", `${versions.node} (${osInfo})`);
else if (process.versions.node) {
map.set("Node", `${process.versions.node} (${osInfo})`);
}
}
}
@@ -88930,7 +88991,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.3";
const constants_SDK_VERSION = "0.3.5";
const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
//# sourceMappingURL=constants.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/retryPolicy.js
@@ -88940,6 +89001,7 @@ const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
const retryPolicyLogger = createClientLogger("ts-http-runtime retryPolicy");
/**
* The programmatic identifier of the retryPolicy.
@@ -88970,11 +89032,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.
responseError = e;
if (!e || responseError.name !== "RestError") {
if (!restError_isRestError(e)) {
throw e;
}
response = responseError.response;
responseError = e;
response = e.response;
}
if (request.abortSignal?.aborted) {
logger.error(`Retry ${retryCount}: Request aborted.`);
@@ -89375,16 +89437,15 @@ 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, { headers });
cachedAgents.httpProxyAgent = new http_proxy_agent_dist.HttpProxyAgent(proxyUrl);
}
request.agent = cachedAgents.httpProxyAgent;
}
else {
if (!cachedAgents.httpsProxyAgent) {
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl, { headers });
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl);
}
request.agent = cachedAgents.httpsProxyAgent;
}
@@ -89436,13 +89497,13 @@ function typeGuards_isBinaryBody(body) {
(body instanceof Uint8Array ||
typeGuards_isReadableStream(body) ||
typeof body === "function" ||
body instanceof Blob));
(typeof Blob !== "undefined" && body instanceof Blob)));
}
function typeGuards_isReadableStream(x) {
return isNodeReadableStream(x) || isWebReadableStream(x);
}
function isBlob(x) {
return typeof x.stream === "function";
function typeGuards_isBlob(x) {
return typeof Blob !== "undefined" && x instanceof Blob;
}
//# sourceMappingURL=typeGuards.js.map
// EXTERNAL MODULE: external "stream"
@@ -89488,7 +89549,7 @@ function toStream(source) {
if (source instanceof Uint8Array) {
return external_stream_.Readable.from(Buffer.from(source));
}
else if (isBlob(source)) {
else if (typeGuards_isBlob(source)) {
return ensureNodeStream(source.stream());
}
else {
@@ -89538,7 +89599,7 @@ function getLength(source) {
if (source instanceof Uint8Array) {
return source.byteLength;
}
else if (isBlob(source)) {
else if (typeGuards_isBlob(source)) {
// if was created using createFile then -1 means we have an unknown size
return source.size === -1 ? undefined : source.size;
}
@@ -90067,9 +90128,14 @@ async function sendRequest_sendRequest(method, url, pipeline, options = {}, cust
* @returns returns the content-type
*/
function getRequestContentType(options = {}) {
return (options.contentType ??
options.headers?.["content-type"] ??
getContentType(options.body));
if (options.contentType) {
return options.contentType;
}
const headerContentType = options.headers?.["content-type"];
if (typeof headerContentType === "string") {
return headerContentType;
}
return getContentType(options.body);
}
/**
* Function to determine the content-type of a body
@@ -90084,6 +90150,9 @@ 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);
@@ -90134,9 +90203,15 @@ 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) };
}
@@ -90326,8 +90401,6 @@ function statusCodeToNumber(statusCode) {
//# sourceMappingURL=index.js.map
;// CONCATENATED MODULE: ./node_modules/@azure/core-rest-pipeline/dist/esm/pipeline.js
// Copyright (c) Microsoft Corporation.
@@ -90524,59 +90597,6 @@ 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.
+100 -80
View File
@@ -85596,13 +85596,13 @@ class Sanitizer {
message: value.message,
};
}
if (key === "headers") {
if (key === "headers" && isObject(value)) {
return this.sanitizeHeaders(value);
}
else if (key === "url") {
else if (key === "url" && typeof value === "string") {
return this.sanitizeUrl(value);
}
else if (key === "query") {
else if (key === "query" && isObject(value)) {
return this.sanitizeQuery(value);
}
else if (key === "body") {
@@ -86173,6 +86173,68 @@ 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.
@@ -86190,15 +86252,14 @@ function getHeaderName() {
async function userAgentPlatform_setPlatformSpecificData(map) {
if (process && process.versions) {
const osInfo = `${os.type()} ${os.release()}; ${os.arch()}`;
const versions = process.versions;
if (versions.bun) {
map.set("Bun", `${versions.bun} (${osInfo})`);
if (process.versions.bun) {
map.set("Bun", `${process.versions.bun} (${osInfo})`);
}
else if (versions.deno) {
map.set("Deno", `${versions.deno} (${osInfo})`);
else if (process.versions.deno) {
map.set("Deno", `${process.versions.deno} (${osInfo})`);
}
else if (versions.node) {
map.set("Node", `${versions.node} (${osInfo})`);
else if (process.versions.node) {
map.set("Node", `${process.versions.node} (${osInfo})`);
}
}
}
@@ -86505,7 +86566,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.3";
const constants_SDK_VERSION = "0.3.5";
const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
//# sourceMappingURL=constants.js.map
;// CONCATENATED MODULE: ./node_modules/@typespec/ts-http-runtime/dist/esm/policies/retryPolicy.js
@@ -86515,6 +86576,7 @@ const constants_DEFAULT_RETRY_POLICY_COUNT = 3;
const retryPolicyLogger = createClientLogger("ts-http-runtime retryPolicy");
/**
* The programmatic identifier of the retryPolicy.
@@ -86545,11 +86607,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.
responseError = e;
if (!e || responseError.name !== "RestError") {
if (!restError_isRestError(e)) {
throw e;
}
response = responseError.response;
responseError = e;
response = e.response;
}
if (request.abortSignal?.aborted) {
logger.error(`Retry ${retryCount}: Request aborted.`);
@@ -86950,16 +87012,15 @@ 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, { headers });
cachedAgents.httpProxyAgent = new http_proxy_agent_dist.HttpProxyAgent(proxyUrl);
}
request.agent = cachedAgents.httpProxyAgent;
}
else {
if (!cachedAgents.httpsProxyAgent) {
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl, { headers });
cachedAgents.httpsProxyAgent = new dist.HttpsProxyAgent(proxyUrl);
}
request.agent = cachedAgents.httpsProxyAgent;
}
@@ -87011,13 +87072,13 @@ function typeGuards_isBinaryBody(body) {
(body instanceof Uint8Array ||
typeGuards_isReadableStream(body) ||
typeof body === "function" ||
body instanceof Blob));
(typeof Blob !== "undefined" && body instanceof Blob)));
}
function typeGuards_isReadableStream(x) {
return isNodeReadableStream(x) || isWebReadableStream(x);
}
function isBlob(x) {
return typeof x.stream === "function";
function typeGuards_isBlob(x) {
return typeof Blob !== "undefined" && x instanceof Blob;
}
//# sourceMappingURL=typeGuards.js.map
// EXTERNAL MODULE: external "stream"
@@ -87063,7 +87124,7 @@ function toStream(source) {
if (source instanceof Uint8Array) {
return external_stream_.Readable.from(Buffer.from(source));
}
else if (isBlob(source)) {
else if (typeGuards_isBlob(source)) {
return ensureNodeStream(source.stream());
}
else {
@@ -87113,7 +87174,7 @@ function getLength(source) {
if (source instanceof Uint8Array) {
return source.byteLength;
}
else if (isBlob(source)) {
else if (typeGuards_isBlob(source)) {
// if was created using createFile then -1 means we have an unknown size
return source.size === -1 ? undefined : source.size;
}
@@ -87642,9 +87703,14 @@ async function sendRequest_sendRequest(method, url, pipeline, options = {}, cust
* @returns returns the content-type
*/
function getRequestContentType(options = {}) {
return (options.contentType ??
options.headers?.["content-type"] ??
getContentType(options.body));
if (options.contentType) {
return options.contentType;
}
const headerContentType = options.headers?.["content-type"];
if (typeof headerContentType === "string") {
return headerContentType;
}
return getContentType(options.body);
}
/**
* Function to determine the content-type of a body
@@ -87659,6 +87725,9 @@ 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);
@@ -87709,9 +87778,15 @@ 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) };
}
@@ -87901,8 +87976,6 @@ function statusCodeToNumber(statusCode) {
//# sourceMappingURL=index.js.map
;// CONCATENATED MODULE: ./node_modules/@azure/core-rest-pipeline/dist/esm/pipeline.js
// Copyright (c) Microsoft Corporation.
@@ -88099,59 +88172,6 @@ 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.
+5 -5
View File
@@ -1,12 +1,12 @@
{
"name": "upload-artifact",
"version": "7.0.0",
"version": "7.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "upload-artifact",
"version": "7.0.0",
"version": "7.0.1",
"license": "MIT",
"dependencies": {
"@actions/artifact": "^6.2.0",
@@ -2477,9 +2477,9 @@
}
},
"node_modules/@typespec/ts-http-runtime": {
"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==",
"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==",
"license": "MIT",
"dependencies": {
"http-proxy-agent": "^7.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "upload-artifact",
"version": "7.0.0",
"version": "7.0.1",
"description": "Upload an Actions Artifact in a workflow run",
"type": "module",
"main": "dist/upload/index.js",