Compare commits

...

3 Commits

Author SHA1 Message Date
Josh Gross f626d210e8
linting 2024-08-15 20:37:17 -04:00
Josh Gross fa37431cef
`npm ci` and `npm run release` 2024-08-15 20:34:01 -04:00
Josh Gross 3412bb46a4
Exclude the `.git` directory by default 2024-08-15 20:29:20 -04:00
18 changed files with 248 additions and 20 deletions

View File

@ -16,6 +16,7 @@ See also [download-artifact](https://github.com/actions/download-artifact).
- [Breaking Changes](#breaking-changes) - [Breaking Changes](#breaking-changes)
- [Usage](#usage) - [Usage](#usage)
- [Inputs](#inputs) - [Inputs](#inputs)
- [Uploading the `.git` directory](#uploading-the-git-directory)
- [Outputs](#outputs) - [Outputs](#outputs)
- [Examples](#examples) - [Examples](#examples)
- [Upload an Individual File](#upload-an-individual-file) - [Upload an Individual File](#upload-an-individual-file)
@ -64,6 +65,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. 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. 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, the `.git` directory is excluded by default.
For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md). For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
@ -109,6 +111,30 @@ For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
overwrite: overwrite:
``` ```
#### Uploading the `.git` directory
By default, files in a `.git` directory are ignored in the uploaded artifact.
This is intended to prevent accidentally uploading Git credentials into an artifact that could then
be extracted.
If files in the `.git` directory are needed, ensure that `actions/checkout` is being used with
`persist-credentials: false`.
```yaml
jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false # Ensure credentials are not saved in `.git/config`
- uses: actions/upload-artifact@v4
with:
path: .
include-git-directory: true
```
### Outputs ### Outputs
| Name | Description | Example | | Name | Description | Example |

View File

@ -61,6 +61,12 @@ const lonelyFilePath = path.join(
'lonely-file.txt' 'lonely-file.txt'
) )
const gitConfigPath = path.join(root, '.git', 'config')
const gitHeadPath = path.join(root, '.git', 'HEAD')
const nestedGitConfigPath = path.join(root, 'repository-name', '.git', 'config')
const nestedGitHeadPath = path.join(root, 'repository-name', '.git', 'HEAD')
describe('Search', () => { describe('Search', () => {
beforeAll(async () => { beforeAll(async () => {
// mock all output so that there is less noise when running tests // mock all output so that there is less noise when running tests
@ -93,6 +99,11 @@ describe('Search', () => {
recursive: true recursive: true
}) })
await fs.mkdir(path.join(root, '.git'))
await fs.mkdir(path.join(root, 'repository-name', '.git'), {
recursive: true
})
await fs.writeFile(searchItem1Path, 'search item1 file') await fs.writeFile(searchItem1Path, 'search item1 file')
await fs.writeFile(searchItem2Path, 'search item2 file') await fs.writeFile(searchItem2Path, 'search item2 file')
await fs.writeFile(searchItem3Path, 'search item3 file') await fs.writeFile(searchItem3Path, 'search item3 file')
@ -110,9 +121,17 @@ describe('Search', () => {
await fs.writeFile(amazingFileInFolderHPath, 'amazing file') await fs.writeFile(amazingFileInFolderHPath, 'amazing file')
await fs.writeFile(lonelyFilePath, 'all by itself') await fs.writeFile(lonelyFilePath, 'all by itself')
await fs.writeFile(gitConfigPath, 'git config file')
await fs.writeFile(gitHeadPath, 'git head file')
await fs.writeFile(nestedGitConfigPath, 'nested git config file')
await fs.writeFile(nestedGitHeadPath, 'nested git head file')
/* /*
Directory structure of files that get created: Directory structure of files that get created:
root/ root/
.git/
config
HEAD
folder-a/ folder-a/
folder-b/ folder-b/
folder-c/ folder-c/
@ -136,6 +155,10 @@ describe('Search', () => {
folder-j/ folder-j/
folder-k/ folder-k/
lonely-file.txt lonely-file.txt
repository-name/
.git/
config
HEAD
search-item5.txt search-item5.txt
*/ */
}) })
@ -352,4 +375,18 @@ describe('Search', () => {
) )
expect(searchResult.filesToUpload.includes(lonelyFilePath)).toEqual(true) expect(searchResult.filesToUpload.includes(lonelyFilePath)).toEqual(true)
}) })
it('Excludes .git directory by default', async () => {
const searchResult = await findFilesToUpload(root)
expect(searchResult.filesToUpload.length).toEqual(13)
expect(searchResult.filesToUpload).not.toContain(gitConfigPath)
})
it('Includes .git directory when includeGitDirectory is true', async () => {
const searchResult = await findFilesToUpload(root, {
includeGitDirectory: true
})
expect(searchResult.filesToUpload.length).toEqual(17)
expect(searchResult.filesToUpload).toContain(gitConfigPath)
})
}) })

View File

@ -40,6 +40,9 @@ inputs:
If false, the action will fail if an artifact for the given name already exists. If false, the action will fail if an artifact for the given name already exists.
Does not fail if the artifact does not exist. Does not fail if the artifact does not exist.
default: 'false' default: 'false'
include-git-directory:
description: 'Include files in the .git directory in the artifact.'
default: 'false'
outputs: outputs:
artifact-id: artifact-id:

27
dist/merge/index.js vendored
View File

@ -125727,6 +125727,7 @@ var Inputs;
Inputs["RetentionDays"] = "retention-days"; Inputs["RetentionDays"] = "retention-days";
Inputs["CompressionLevel"] = "compression-level"; Inputs["CompressionLevel"] = "compression-level";
Inputs["DeleteMerged"] = "delete-merged"; Inputs["DeleteMerged"] = "delete-merged";
Inputs["IncludeGitDirectory"] = "include-git-directory";
})(Inputs = exports.Inputs || (exports.Inputs = {})); })(Inputs = exports.Inputs || (exports.Inputs = {}));
@ -125810,13 +125811,15 @@ function getInputs() {
const pattern = core.getInput(constants_1.Inputs.Pattern, { required: true }); const pattern = core.getInput(constants_1.Inputs.Pattern, { required: true });
const separateDirectories = core.getBooleanInput(constants_1.Inputs.SeparateDirectories); const separateDirectories = core.getBooleanInput(constants_1.Inputs.SeparateDirectories);
const deleteMerged = core.getBooleanInput(constants_1.Inputs.DeleteMerged); const deleteMerged = core.getBooleanInput(constants_1.Inputs.DeleteMerged);
const includeGitDirectory = core.getBooleanInput(constants_1.Inputs.IncludeGitDirectory);
const inputs = { const inputs = {
name, name,
pattern, pattern,
separateDirectories, separateDirectories,
deleteMerged, deleteMerged,
retentionDays: 0, retentionDays: 0,
compressionLevel: 6 compressionLevel: 6,
includeGitDirectory
}; };
const retentionDaysStr = core.getInput(constants_1.Inputs.RetentionDays); const retentionDaysStr = core.getInput(constants_1.Inputs.RetentionDays);
if (retentionDaysStr) { if (retentionDaysStr) {
@ -125932,7 +125935,9 @@ function run() {
if (typeof inputs.compressionLevel !== 'undefined') { if (typeof inputs.compressionLevel !== 'undefined') {
options.compressionLevel = inputs.compressionLevel; options.compressionLevel = inputs.compressionLevel;
} }
const searchResult = yield (0, search_1.findFilesToUpload)(tmpDir); const searchResult = yield (0, search_1.findFilesToUpload)(tmpDir, {
includeGitDirectory: inputs.includeGitDirectory
});
yield (0, upload_artifact_1.uploadArtifact)(inputs.name, searchResult.filesToUpload, searchResult.rootDirectory, options); yield (0, upload_artifact_1.uploadArtifact)(inputs.name, searchResult.filesToUpload, searchResult.rootDirectory, options);
core.info(`The ${artifacts.length} artifact(s) have been successfully merged!`); core.info(`The ${artifacts.length} artifact(s) have been successfully merged!`);
if (inputs.deleteMerged) { if (inputs.deleteMerged) {
@ -126057,10 +126062,10 @@ function getMultiPathLCA(searchPaths) {
} }
return path.join(...commonPaths); return path.join(...commonPaths);
} }
function findFilesToUpload(searchPath, globOptions) { function findFilesToUpload(searchPath, searchOptions) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const searchResults = []; const searchResults = [];
const globber = yield glob.create(searchPath, globOptions || getDefaultGlobOptions()); const globber = yield glob.create(searchPath, getDefaultGlobOptions());
const rawSearchResults = yield globber.glob(); const rawSearchResults = yield globber.glob();
/* /*
Files are saved with case insensitivity. Uploading both a.txt and A.txt will files to be overwritten Files are saved with case insensitivity. Uploading both a.txt and A.txt will files to be overwritten
@ -126076,6 +126081,10 @@ function findFilesToUpload(searchPath, globOptions) {
// isDirectory() returns false for symlinks if using fs.lstat(), make sure to use fs.stat() instead // isDirectory() returns false for symlinks if using fs.lstat(), make sure to use fs.stat() instead
if (!fileStats.isDirectory()) { if (!fileStats.isDirectory()) {
(0, core_1.debug)(`File:${searchResult} was found using the provided searchPath`); (0, core_1.debug)(`File:${searchResult} was found using the provided searchPath`);
if (!(searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.includeGitDirectory) && inGitDirectory(searchResult)) {
(0, core_1.debug)(`Ignoring ${searchResult} because it is in the .git directory`);
continue;
}
searchResults.push(searchResult); searchResults.push(searchResult);
// detect any files that would be overwritten because of case insensitivity // detect any files that would be overwritten because of case insensitivity
if (set.has(searchResult.toLowerCase())) { if (set.has(searchResult.toLowerCase())) {
@ -126117,6 +126126,16 @@ function findFilesToUpload(searchPath, globOptions) {
}); });
} }
exports.findFilesToUpload = findFilesToUpload; exports.findFilesToUpload = findFilesToUpload;
function inGitDirectory(filePath) {
// The .git directory is a directory, so we need to check if the file path is a directory
// and if it is a .git directory
for (const part of filePath.split(path.sep)) {
if (part === '.git') {
return true;
}
}
return false;
}
/***/ }), /***/ }),

27
dist/upload/index.js vendored
View File

@ -125815,10 +125815,10 @@ function getMultiPathLCA(searchPaths) {
} }
return path.join(...commonPaths); return path.join(...commonPaths);
} }
function findFilesToUpload(searchPath, globOptions) { function findFilesToUpload(searchPath, searchOptions) {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const searchResults = []; const searchResults = [];
const globber = yield glob.create(searchPath, globOptions || getDefaultGlobOptions()); const globber = yield glob.create(searchPath, getDefaultGlobOptions());
const rawSearchResults = yield globber.glob(); const rawSearchResults = yield globber.glob();
/* /*
Files are saved with case insensitivity. Uploading both a.txt and A.txt will files to be overwritten Files are saved with case insensitivity. Uploading both a.txt and A.txt will files to be overwritten
@ -125834,6 +125834,10 @@ function findFilesToUpload(searchPath, globOptions) {
// isDirectory() returns false for symlinks if using fs.lstat(), make sure to use fs.stat() instead // isDirectory() returns false for symlinks if using fs.lstat(), make sure to use fs.stat() instead
if (!fileStats.isDirectory()) { if (!fileStats.isDirectory()) {
(0, core_1.debug)(`File:${searchResult} was found using the provided searchPath`); (0, core_1.debug)(`File:${searchResult} was found using the provided searchPath`);
if (!(searchOptions === null || searchOptions === void 0 ? void 0 : searchOptions.includeGitDirectory) && inGitDirectory(searchResult)) {
(0, core_1.debug)(`Ignoring ${searchResult} because it is in the .git directory`);
continue;
}
searchResults.push(searchResult); searchResults.push(searchResult);
// detect any files that would be overwritten because of case insensitivity // detect any files that would be overwritten because of case insensitivity
if (set.has(searchResult.toLowerCase())) { if (set.has(searchResult.toLowerCase())) {
@ -125875,6 +125879,16 @@ function findFilesToUpload(searchPath, globOptions) {
}); });
} }
exports.findFilesToUpload = findFilesToUpload; exports.findFilesToUpload = findFilesToUpload;
function inGitDirectory(filePath) {
// The .git directory is a directory, so we need to check if the file path is a directory
// and if it is a .git directory
for (const part of filePath.split(path.sep)) {
if (part === '.git') {
return true;
}
}
return false;
}
/***/ }), /***/ }),
@ -125956,6 +125970,7 @@ var Inputs;
Inputs["RetentionDays"] = "retention-days"; Inputs["RetentionDays"] = "retention-days";
Inputs["CompressionLevel"] = "compression-level"; Inputs["CompressionLevel"] = "compression-level";
Inputs["Overwrite"] = "overwrite"; Inputs["Overwrite"] = "overwrite";
Inputs["IncludeGitDirectory"] = "include-git-directory";
})(Inputs = exports.Inputs || (exports.Inputs = {})); })(Inputs = exports.Inputs || (exports.Inputs = {}));
var NoFileOptions; var NoFileOptions;
(function (NoFileOptions) { (function (NoFileOptions) {
@ -126053,6 +126068,7 @@ function getInputs() {
const name = core.getInput(constants_1.Inputs.Name); const name = core.getInput(constants_1.Inputs.Name);
const path = core.getInput(constants_1.Inputs.Path, { required: true }); const path = core.getInput(constants_1.Inputs.Path, { required: true });
const overwrite = core.getBooleanInput(constants_1.Inputs.Overwrite); const overwrite = core.getBooleanInput(constants_1.Inputs.Overwrite);
const includeGitDirectory = core.getBooleanInput(constants_1.Inputs.IncludeGitDirectory);
const ifNoFilesFound = core.getInput(constants_1.Inputs.IfNoFilesFound); const ifNoFilesFound = core.getInput(constants_1.Inputs.IfNoFilesFound);
const noFileBehavior = constants_1.NoFileOptions[ifNoFilesFound]; const noFileBehavior = constants_1.NoFileOptions[ifNoFilesFound];
if (!noFileBehavior) { if (!noFileBehavior) {
@ -126062,7 +126078,8 @@ function getInputs() {
artifactName: name, artifactName: name,
searchPath: path, searchPath: path,
ifNoFilesFound: noFileBehavior, ifNoFilesFound: noFileBehavior,
overwrite: overwrite overwrite: overwrite,
includeGitDirectory: includeGitDirectory
}; };
const retentionDaysStr = core.getInput(constants_1.Inputs.RetentionDays); const retentionDaysStr = core.getInput(constants_1.Inputs.RetentionDays);
if (retentionDaysStr) { if (retentionDaysStr) {
@ -126151,7 +126168,9 @@ function deleteArtifactIfExists(artifactName) {
function run() { function run() {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
const inputs = (0, input_helper_1.getInputs)(); const inputs = (0, input_helper_1.getInputs)();
const searchResult = yield (0, search_1.findFilesToUpload)(inputs.searchPath); const searchResult = yield (0, search_1.findFilesToUpload)(inputs.searchPath, {
includeGitDirectory: inputs.includeGitDirectory
});
if (searchResult.filesToUpload.length === 0) { if (searchResult.filesToUpload.length === 0) {
// No files were found, different use cases warrant different types of behavior if nothing is found // No files were found, different use cases warrant different types of behavior if nothing is found
switch (inputs.ifNoFilesFound) { switch (inputs.ifNoFilesFound) {

View File

@ -207,3 +207,41 @@ jobs:
``` ```
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). 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).
## `.git` Directory
By default, files in the `.git` directory are ignored to avoid unintentionally uploading
credentials.
In versions of this action before `v4.4.0`, files in the `.git` directory were included by default.
If this directory is required, ensure credentials are not saved in `.git/config` and then
enable the `include-git-directory` input.
```yaml
jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
path: .
```
```diff
jobs:
upload:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
+ with:
+ persist-credentials: false
- name: Upload Artifact
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
path: .
+ include-git-directory: true
```

View File

@ -5,6 +5,7 @@ Merge multiple [Actions Artifacts](https://docs.github.com/en/actions/using-work
- [`@actions/upload-artifact/merge`](#actionsupload-artifactmerge) - [`@actions/upload-artifact/merge`](#actionsupload-artifactmerge)
- [Usage](#usage) - [Usage](#usage)
- [Inputs](#inputs) - [Inputs](#inputs)
- [Uploading the `.git` directory](#uploading-the-git-directory)
- [Outputs](#outputs) - [Outputs](#outputs)
- [Examples](#examples) - [Examples](#examples)
- [Combining all artifacts in a workflow run](#combining-all-artifacts-in-a-workflow-run) - [Combining all artifacts in a workflow run](#combining-all-artifacts-in-a-workflow-run)
@ -59,6 +60,44 @@ For most cases, this may not be the most efficient solution. See [the migration
compression-level: compression-level:
``` ```
#### Uploading the `.git` directory
By default, files in a `.git` directory are ignored in the merged artifact.
This is intended to prevent accidentally uploading Git credentials into an artifact that could then
be extracted.
If files in the `.git` directory are needed, ensure that `actions/checkout` is being used with
`persist-credentials: false`.
```yaml
jobs:
upload:
runs-on: ubuntu-latest
strategy:
matrix:
foo: [a, b, c]
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false # Ensure credentials are not saved in `.git/config`
- name: Upload
uses: actions/upload-artifact@v4
with:
name: my-artifact-${{ matrix.foo }}
path: .
include-git-directory: true
merge:
runs-on: ubuntu-latest
steps:
- uses: actions/upload-artifact/merge@v4
with:
include-git-directory: true
```
### Outputs ### Outputs
| Name | Description | Example | | Name | Description | Example |

View File

@ -36,6 +36,9 @@ inputs:
If true, the artifacts that were merged will be deleted. If true, the artifacts that were merged will be deleted.
If false, the artifacts will still exist. If false, the artifacts will still exist.
default: 'false' default: 'false'
include-git-directory:
description: 'Include files in the .git directory in the merged artifact.'
default: 'false'
outputs: outputs:
artifact-id: artifact-id:

View File

@ -1,6 +1,6 @@
{ {
"name": "upload-artifact", "name": "upload-artifact",
"version": "4.3.6", "version": "4.4.0",
"description": "Upload an Actions Artifact in a workflow run", "description": "Upload an Actions Artifact in a workflow run",
"main": "dist/upload/index.js", "main": "dist/upload/index.js",
"scripts": { "scripts": {

View File

@ -5,5 +5,6 @@ export enum Inputs {
SeparateDirectories = 'separate-directories', SeparateDirectories = 'separate-directories',
RetentionDays = 'retention-days', RetentionDays = 'retention-days',
CompressionLevel = 'compression-level', CompressionLevel = 'compression-level',
DeleteMerged = 'delete-merged' DeleteMerged = 'delete-merged',
IncludeGitDirectory = 'include-git-directory'
} }

View File

@ -10,6 +10,7 @@ export function getInputs(): MergeInputs {
const pattern = core.getInput(Inputs.Pattern, {required: true}) const pattern = core.getInput(Inputs.Pattern, {required: true})
const separateDirectories = core.getBooleanInput(Inputs.SeparateDirectories) const separateDirectories = core.getBooleanInput(Inputs.SeparateDirectories)
const deleteMerged = core.getBooleanInput(Inputs.DeleteMerged) const deleteMerged = core.getBooleanInput(Inputs.DeleteMerged)
const includeGitDirectory = core.getBooleanInput(Inputs.IncludeGitDirectory)
const inputs = { const inputs = {
name, name,
@ -17,7 +18,8 @@ export function getInputs(): MergeInputs {
separateDirectories, separateDirectories,
deleteMerged, deleteMerged,
retentionDays: 0, retentionDays: 0,
compressionLevel: 6 compressionLevel: 6,
includeGitDirectory
} as MergeInputs } as MergeInputs
const retentionDaysStr = core.getInput(Inputs.RetentionDays) const retentionDaysStr = core.getInput(Inputs.RetentionDays)

View File

@ -62,7 +62,9 @@ export async function run(): Promise<void> {
options.compressionLevel = inputs.compressionLevel options.compressionLevel = inputs.compressionLevel
} }
const searchResult = await findFilesToUpload(tmpDir) const searchResult = await findFilesToUpload(tmpDir, {
includeGitDirectory: inputs.includeGitDirectory
})
await uploadArtifact( await uploadArtifact(
inputs.name, inputs.name,

View File

@ -30,4 +30,9 @@ export interface MergeInputs {
* If false, the artifacts will be merged into the root of the destination. * If false, the artifacts will be merged into the root of the destination.
*/ */
separateDirectories: boolean separateDirectories: boolean
/**
* Include files in the `.git` directory in the artifact
*/
includeGitDirectory: boolean
} }

View File

@ -78,15 +78,21 @@ function getMultiPathLCA(searchPaths: string[]): string {
return path.join(...commonPaths) return path.join(...commonPaths)
} }
export interface SearchOptions {
/**
* Indicates whether files in the .git directory should be included in the artifact
*
* @default false
*/
includeGitDirectory: boolean
}
export async function findFilesToUpload( export async function findFilesToUpload(
searchPath: string, searchPath: string,
globOptions?: glob.GlobOptions searchOptions?: SearchOptions
): Promise<SearchResult> { ): Promise<SearchResult> {
const searchResults: string[] = [] const searchResults: string[] = []
const globber = await glob.create( const globber = await glob.create(searchPath, getDefaultGlobOptions())
searchPath,
globOptions || getDefaultGlobOptions()
)
const rawSearchResults: string[] = await globber.glob() const rawSearchResults: string[] = await globber.glob()
/* /*
@ -104,6 +110,12 @@ export async function findFilesToUpload(
// isDirectory() returns false for symlinks if using fs.lstat(), make sure to use fs.stat() instead // isDirectory() returns false for symlinks if using fs.lstat(), make sure to use fs.stat() instead
if (!fileStats.isDirectory()) { if (!fileStats.isDirectory()) {
debug(`File:${searchResult} was found using the provided searchPath`) debug(`File:${searchResult} was found using the provided searchPath`)
if (!searchOptions?.includeGitDirectory && inGitDirectory(searchResult)) {
debug(`Ignoring ${searchResult} because it is in the .git directory`)
continue
}
searchResults.push(searchResult) searchResults.push(searchResult)
// detect any files that would be overwritten because of case insensitivity // detect any files that would be overwritten because of case insensitivity
@ -155,3 +167,15 @@ export async function findFilesToUpload(
rootDirectory: searchPaths[0] rootDirectory: searchPaths[0]
} }
} }
function inGitDirectory(filePath: string): boolean {
// The .git directory is a directory, so we need to check if the file path is a directory
// and if it is a .git directory
for (const part of filePath.split(path.sep)) {
if (part === '.git') {
return true
}
}
return false
}

View File

@ -5,7 +5,8 @@ export enum Inputs {
IfNoFilesFound = 'if-no-files-found', IfNoFilesFound = 'if-no-files-found',
RetentionDays = 'retention-days', RetentionDays = 'retention-days',
CompressionLevel = 'compression-level', CompressionLevel = 'compression-level',
Overwrite = 'overwrite' Overwrite = 'overwrite',
IncludeGitDirectory = 'include-git-directory'
} }
export enum NoFileOptions { export enum NoFileOptions {

View File

@ -9,6 +9,7 @@ export function getInputs(): UploadInputs {
const name = core.getInput(Inputs.Name) const name = core.getInput(Inputs.Name)
const path = core.getInput(Inputs.Path, {required: true}) const path = core.getInput(Inputs.Path, {required: true})
const overwrite = core.getBooleanInput(Inputs.Overwrite) const overwrite = core.getBooleanInput(Inputs.Overwrite)
const includeGitDirectory = core.getBooleanInput(Inputs.IncludeGitDirectory)
const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound) const ifNoFilesFound = core.getInput(Inputs.IfNoFilesFound)
const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound] const noFileBehavior: NoFileOptions = NoFileOptions[ifNoFilesFound]
@ -27,7 +28,8 @@ export function getInputs(): UploadInputs {
artifactName: name, artifactName: name,
searchPath: path, searchPath: path,
ifNoFilesFound: noFileBehavior, ifNoFilesFound: noFileBehavior,
overwrite: overwrite overwrite: overwrite,
includeGitDirectory: includeGitDirectory
} as UploadInputs } as UploadInputs
const retentionDaysStr = core.getInput(Inputs.RetentionDays) const retentionDaysStr = core.getInput(Inputs.RetentionDays)

View File

@ -24,7 +24,9 @@ async function deleteArtifactIfExists(artifactName: string): Promise<void> {
export async function run(): Promise<void> { export async function run(): Promise<void> {
const inputs = getInputs() const inputs = getInputs()
const searchResult = await findFilesToUpload(inputs.searchPath) const searchResult = await findFilesToUpload(inputs.searchPath, {
includeGitDirectory: inputs.includeGitDirectory
})
if (searchResult.filesToUpload.length === 0) { if (searchResult.filesToUpload.length === 0) {
// No files were found, different use cases warrant different types of behavior if nothing is found // No files were found, different use cases warrant different types of behavior if nothing is found
switch (inputs.ifNoFilesFound) { switch (inputs.ifNoFilesFound) {

View File

@ -30,4 +30,9 @@ export interface UploadInputs {
* Whether or not to replace an existing artifact with the same name * Whether or not to replace an existing artifact with the same name
*/ */
overwrite: boolean overwrite: boolean
/**
* Include files in the `.git` directory in the artifact
*/
includeGitDirectory: boolean
} }