Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: actions/upload-artifact
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.3.6
Choose a base ref
...
head repository: actions/upload-artifact
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.4.0
Choose a head ref
  • 10 commits
  • 19 files changed
  • 1 contributor

Commits on Aug 15, 2024

  1. Exclude hidden files by default

    joshmgross committed Aug 15, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    crazy-max CrazyMax
    Copy the full SHA
    cb6558b View commit details
  2. lint

    joshmgross committed Aug 15, 2024
    Copy the full SHA
    acb59e4 View commit details
  3. Update to latest @actions/glob and fix tests

    joshmgross committed Aug 15, 2024
    1
    Copy the full SHA
    a0c40cf View commit details
  4. npm run release

    joshmgross committed Aug 15, 2024
    Copy the full SHA
    0a398c1 View commit details
  5. Update glob license

    joshmgross committed Aug 15, 2024
    Copy the full SHA
    453e8d0 View commit details
  6. Remove another trailing comma

    joshmgross committed Aug 15, 2024
    Copy the full SHA
    3be2180 View commit details
  7. npm run release again 🙂

    joshmgross committed Aug 15, 2024
    Copy the full SHA
    3b315f2 View commit details
  8. Copy the full SHA
    710f362 View commit details
  9. Add a warning about enabling include-hidden-files

    joshmgross committed Aug 15, 2024
    Copy the full SHA
    d52396a View commit details

Commits on Aug 29, 2024

  1. Merge pull request #598 from actions/joshmgross/exclude-hidden-files

    Exclude hidden files by default
    joshmgross authored Aug 29, 2024
    4
    Copy the full SHA
    5076954 View commit details
2 changes: 1 addition & 1 deletion .licenses/npm/@actions/glob.dep.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -64,6 +64,7 @@ There is also a new sub-action, `actions/upload-artifact/merge`. For more info,
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).

@@ -107,6 +108,12 @@ For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
# Does not fail if the artifact does not exist.
# Optional. Default is 'false'
overwrite:

# Whether to include hidden files in the provided path in the artifact
# The file contents of any hidden files in the path should be validated before
# enabled this to avoid uploading sensitive information.
# Optional. Default is 'false'
include-hidden-files:
```
### Outputs
52 changes: 52 additions & 0 deletions __tests__/search.test.ts
Original file line number Diff line number Diff line change
@@ -61,6 +61,20 @@ const lonelyFilePath = path.join(
'lonely-file.txt'
)

const hiddenFile = path.join(root, '.hidden-file.txt')
const fileInHiddenFolderPath = path.join(
root,
'.hidden-folder',
'folder-in-hidden-folder',
'file.txt'
)
const fileInHiddenFolderInFolderA = path.join(
root,
'folder-a',
'.hidden-folder-in-folder-a',
'file.txt'
)

describe('Search', () => {
beforeAll(async () => {
// mock all output so that there is less noise when running tests
@@ -93,6 +107,14 @@ describe('Search', () => {
recursive: true
})

await fs.mkdir(
path.join(root, '.hidden-folder', 'folder-in-hidden-folder'),
{recursive: true}
)
await fs.mkdir(path.join(root, 'folder-a', '.hidden-folder-in-folder-a'), {
recursive: true
})

await fs.writeFile(searchItem1Path, 'search item1 file')
await fs.writeFile(searchItem2Path, 'search item2 file')
await fs.writeFile(searchItem3Path, 'search item3 file')
@@ -110,10 +132,19 @@ describe('Search', () => {
await fs.writeFile(amazingFileInFolderHPath, 'amazing file')

await fs.writeFile(lonelyFilePath, 'all by itself')

await fs.writeFile(hiddenFile, 'hidden file')
await fs.writeFile(fileInHiddenFolderPath, 'file in hidden directory')
await fs.writeFile(fileInHiddenFolderInFolderA, 'file in hidden directory')
/*
Directory structure of files that get created:
root/
.hidden-folder/
folder-in-hidden-folder/
file.txt
folder-a/
.hidden-folder-in-folder-a/
file.txt
folder-b/
folder-c/
search-item1.txt
@@ -136,6 +167,7 @@ describe('Search', () => {
folder-j/
folder-k/
lonely-file.txt
.hidden-file.txt
search-item5.txt
*/
})
@@ -352,4 +384,24 @@ describe('Search', () => {
)
expect(searchResult.filesToUpload.includes(lonelyFilePath)).toEqual(true)
})

it('Hidden files ignored by default', async () => {
const searchPath = path.join(root, '**/*')
const searchResult = await findFilesToUpload(searchPath)

expect(searchResult.filesToUpload).not.toContain(hiddenFile)
expect(searchResult.filesToUpload).not.toContain(fileInHiddenFolderPath)
expect(searchResult.filesToUpload).not.toContain(
fileInHiddenFolderInFolderA
)
})

it('Hidden files included', async () => {
const searchPath = path.join(root, '**/*')
const searchResult = await findFilesToUpload(searchPath, true)

expect(searchResult.filesToUpload).toContain(hiddenFile)
expect(searchResult.filesToUpload).toContain(fileInHiddenFolderPath)
expect(searchResult.filesToUpload).toContain(fileInHiddenFolderInFolderA)
})
})
5 changes: 5 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -40,6 +40,11 @@ inputs:
If false, the action will fail if an artifact for the given name already exists.
Does not fail if the artifact does not exist.
default: 'false'
include-hidden-files:
description: >
If true, hidden files will be included in the artifact.
If false, hidden files will be excluded from the artifact.
default: 'false'

outputs:
artifact-id:
157 changes: 103 additions & 54 deletions dist/merge/index.js

Large diffs are not rendered by default.

157 changes: 103 additions & 54 deletions dist/upload/index.js

Large diffs are not rendered by default.

61 changes: 50 additions & 11 deletions docs/MIGRATION.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
- [Multiple uploads to the same named Artifact](#multiple-uploads-to-the-same-named-artifact)
- [Overwriting an Artifact](#overwriting-an-artifact)
- [Merging multiple artifacts](#merging-multiple-artifacts)
- [Hidden files](#hidden-files)

Several behavioral differences exist between Artifact actions `v3` and below vs `v4`. This document outlines common scenarios in `v3`, and how they would be handled in `v4`.

@@ -189,21 +190,59 @@ jobs:
- name: Create a File
run: echo "hello from ${{ matrix.runs-on }}" > file-${{ matrix.runs-on }}.txt
- name: Upload Artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
- name: all-my-files
+ name: my-artifact-${{ matrix.runs-on }}
path: file-${{ matrix.runs-on }}.txt
+ merge:
+ runs-on: ubuntu-latest
+ needs: upload
+ steps:
+ - name: Merge Artifacts
+ uses: actions/upload-artifact/merge@v4
+ with:
+ name: all-my-files
+ pattern: my-artifact-*
+ merge:
+ runs-on: ubuntu-latest
+ needs: upload
+ steps:
+ - name: Merge Artifacts
+ uses: actions/upload-artifact/merge@v4
+ with:
+ name: all-my-files
+ pattern: my-artifact-*
```

Note that this will download all artifacts to a temporary directory and reupload them as a single artifact. For more information on inputs and other use cases for `actions/upload-artifact/merge@v4`, see [the action documentation](../merge/README.md).

## Hidden Files

By default, hidden files are ignored by this action to avoid unintentionally uploading sensitive
information.

In versions of this action before v4.4.0, these hidden files were included by default.

If you need to upload hidden files, you can use the `include-hidden-files` input.

```yaml
jobs:
upload:
runs-on: ubuntu-latest
steps:
- name: Create a Hidden File
run: echo "hello from a hidden file" > .hidden-file.txt
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
path: .hidden-file.txt
```


```diff
jobs:
upload:
runs-on: ubuntu-latest
steps:
- name: Create a Hidden File
run: echo "hello from a hidden file" > .hidden-file.txt
- name: Upload Artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
path: .hidden-file.txt
+ include-hidden-files: true
```
5 changes: 5 additions & 0 deletions merge/action.yml
Original file line number Diff line number Diff line change
@@ -36,6 +36,11 @@ inputs:
If true, the artifacts that were merged will be deleted.
If false, the artifacts will still exist.
default: 'false'
include-hidden-files:
description: >
If true, hidden files will be included in the merged artifact.
If false, hidden files will be excluded from the merged artifact.
default: 'false'

outputs:
artifact-id:
22 changes: 11 additions & 11 deletions package-lock.json
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "upload-artifact",
"version": "4.3.6",
"version": "4.4.0",
"description": "Upload an Actions Artifact in a workflow run",
"main": "dist/upload/index.js",
"scripts": {
@@ -32,7 +32,7 @@
"@actions/artifact": "2.1.8",
"@actions/core": "^1.10.1",
"@actions/github": "^6.0.0",
"@actions/glob": "^0.3.0",
"@actions/glob": "^0.5.0",
"@actions/io": "^1.1.2",
"minimatch": "^9.0.3"
},
3 changes: 2 additions & 1 deletion src/merge/constants.ts
Original file line number Diff line number Diff line change
@@ -5,5 +5,6 @@ export enum Inputs {
SeparateDirectories = 'separate-directories',
RetentionDays = 'retention-days',
CompressionLevel = 'compression-level',
DeleteMerged = 'delete-merged'
DeleteMerged = 'delete-merged',
IncludeHiddenFiles = 'include-hidden-files'
}
4 changes: 3 additions & 1 deletion src/merge/input-helper.ts
Original file line number Diff line number Diff line change
@@ -10,14 +10,16 @@ export function getInputs(): MergeInputs {
const pattern = core.getInput(Inputs.Pattern, {required: true})
const separateDirectories = core.getBooleanInput(Inputs.SeparateDirectories)
const deleteMerged = core.getBooleanInput(Inputs.DeleteMerged)
const includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)

const inputs = {
name,
pattern,
separateDirectories,
deleteMerged,
retentionDays: 0,
compressionLevel: 6
compressionLevel: 6,
includeHiddenFiles
} as MergeInputs

const retentionDaysStr = core.getInput(Inputs.RetentionDays)
5 changes: 4 additions & 1 deletion src/merge/merge-artifacts.ts
Original file line number Diff line number Diff line change
@@ -62,7 +62,10 @@ export async function run(): Promise<void> {
options.compressionLevel = inputs.compressionLevel
}

const searchResult = await findFilesToUpload(tmpDir)
const searchResult = await findFilesToUpload(
tmpDir,
inputs.includeHiddenFiles
)

await uploadArtifact(
inputs.name,
5 changes: 5 additions & 0 deletions src/merge/merge-inputs.ts
Original file line number Diff line number Diff line change
@@ -30,4 +30,9 @@ export interface MergeInputs {
* If false, the artifacts will be merged into the root of the destination.
*/
separateDirectories: boolean

/**
* Whether or not to include hidden files in the artifact
*/
includeHiddenFiles: boolean
}
9 changes: 5 additions & 4 deletions src/shared/search.ts
Original file line number Diff line number Diff line change
@@ -11,11 +11,12 @@ export interface SearchResult {
rootDirectory: string
}

function getDefaultGlobOptions(): glob.GlobOptions {
function getDefaultGlobOptions(includeHiddenFiles: boolean): glob.GlobOptions {
return {
followSymbolicLinks: true,
implicitDescendants: true,
omitBrokenSymbolicLinks: true
omitBrokenSymbolicLinks: true,
excludeHiddenFiles: !includeHiddenFiles
}
}

@@ -80,12 +81,12 @@ function getMultiPathLCA(searchPaths: string[]): string {

export async function findFilesToUpload(
searchPath: string,
globOptions?: glob.GlobOptions
includeHiddenFiles?: boolean
): Promise<SearchResult> {
const searchResults: string[] = []
const globber = await glob.create(
searchPath,
globOptions || getDefaultGlobOptions()
getDefaultGlobOptions(includeHiddenFiles || false)
)
const rawSearchResults: string[] = await globber.glob()

3 changes: 2 additions & 1 deletion src/upload/constants.ts
Original file line number Diff line number Diff line change
@@ -5,7 +5,8 @@ export enum Inputs {
IfNoFilesFound = 'if-no-files-found',
RetentionDays = 'retention-days',
CompressionLevel = 'compression-level',
Overwrite = 'overwrite'
Overwrite = 'overwrite',
IncludeHiddenFiles = 'include-hidden-files'
}

export enum NoFileOptions {
4 changes: 3 additions & 1 deletion src/upload/input-helper.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ export function getInputs(): UploadInputs {
const name = core.getInput(Inputs.Name)
const path = core.getInput(Inputs.Path, {required: true})
const overwrite = core.getBooleanInput(Inputs.Overwrite)
const includeHiddenFiles = core.getBooleanInput(Inputs.IncludeHiddenFiles)

const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
@@ -27,7 +28,8 @@ export function getInputs(): UploadInputs {
artifactName: name,
searchPath: path,
ifNoFilesFound: noFileBehavior,
overwrite: overwrite
overwrite: overwrite,
includeHiddenFiles: includeHiddenFiles
} as UploadInputs

const retentionDaysStr = core.getInput(Inputs.RetentionDays)
5 changes: 4 additions & 1 deletion src/upload/upload-artifact.ts
Original file line number Diff line number Diff line change
@@ -24,7 +24,10 @@ async function deleteArtifactIfExists(artifactName: string): Promise<void> {

export async function run(): Promise<void> {
const inputs = getInputs()
const searchResult = await findFilesToUpload(inputs.searchPath)
const searchResult = await findFilesToUpload(
inputs.searchPath,
inputs.includeHiddenFiles
)
if (searchResult.filesToUpload.length === 0) {
// No files were found, different use cases warrant different types of behavior if nothing is found
switch (inputs.ifNoFilesFound) {
5 changes: 5 additions & 0 deletions src/upload/upload-inputs.ts
Original file line number Diff line number Diff line change
@@ -30,4 +30,9 @@ export interface UploadInputs {
* Whether or not to replace an existing artifact with the same name
*/
overwrite: boolean

/**
* Whether or not to include hidden files in the artifact
*/
includeHiddenFiles: boolean
}