Add an option to specify retention days for artifacts (#575)

* Add an option to specify retention days for artifacts

* Validate against settings exposed as env var to give early feedback

* Fix lint

* Add tests and addressing feedback

* Update packages/artifact/__tests__/upload.test.ts

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* Update packages/artifact/README.md

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* Update packages/artifact/src/internal/utils.ts

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

* Update packages/artifact/__tests__/util.test.ts

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>

Co-authored-by: Konrad Pabjan <konradpabjan@github.com>
This commit is contained in:
Yang Cao
2020-09-18 11:30:00 -04:00
committed by GitHub
parent 71b19c1d65
commit ace7a82469
10 changed files with 97 additions and 5 deletions

View File

@@ -45,3 +45,7 @@ export function getRuntimeUrl(): string {
export function getWorkFlowRunId(): string {
return '15'
}
export function getRetentionDays(): string | undefined {
return '45'
}

View File

@@ -94,7 +94,8 @@ export class DefaultArtifactClient implements ArtifactClient {
} else {
// Create an entry for the artifact in the file container
const response = await uploadHttpClient.createArtifactInFileContainer(
name
name,
options
)
if (!response.fileContainerResourceUrl) {
core.debug(response.toString())

View File

@@ -61,3 +61,7 @@ export function getWorkSpaceDirectory(): string {
}
return workspaceDirectory
}
export function getRetentionDays(): string | undefined {
return process.env['GITHUB_RETENTION_DAYS']
}

View File

@@ -11,6 +11,7 @@ export interface ArtifactResponse {
export interface CreateArtifactParameters {
Type: string
Name: string
RetentionDays?: number
}
export interface PatchArtifactSize {

View File

@@ -18,12 +18,14 @@ import {
isForbiddenStatusCode,
displayHttpDiagnostics,
getExponentialRetryTimeInMilliseconds,
tryGetRetryAfterValueTimeInMilliseconds
tryGetRetryAfterValueTimeInMilliseconds,
getProperRetention
} from './utils'
import {
getUploadChunkSize,
getUploadFileConcurrency,
getRetryLimit
getRetryLimit,
getRetentionDays
} from './config-variables'
import {promisify} from 'util'
import {URL} from 'url'
@@ -55,12 +57,23 @@ export class UploadHttpClient {
* @returns The response from the Artifact Service if the file container was successfully created
*/
async createArtifactInFileContainer(
artifactName: string
artifactName: string,
options?: UploadOptions | undefined
): Promise<ArtifactResponse> {
const parameters: CreateArtifactParameters = {
Type: 'actions_storage',
Name: artifactName
}
// calculate retention period
if (options && options.retentionDays) {
const maxRetentionStr = getRetentionDays()
parameters.RetentionDays = getProperRetention(
options.retentionDays,
maxRetentionStr
)
}
const data: string = JSON.stringify(parameters, null, 2)
const artifactUrl = getArtifactUrl()

View File

@@ -15,4 +15,21 @@ export interface UploadOptions {
*
*/
continueOnError?: boolean
/**
* Duration after which artifact will expire in days.
*
* By default artifact expires after 90 days:
* https://docs.github.com/en/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts#downloading-and-deleting-artifacts-after-a-workflow-run-is-complete
*
* Use this option to override the default expiry.
*
* Min value: 1
* Max value: 90 unless changed by repository setting
*
* If this is set to a greater value than the retention settings allowed, the retention on artifacts
* will be reduced to match the max value allowed on server, and the upload process will continue. An
* input of 0 assumes default retention setting.
*/
retentionDays?: number
}

View File

@@ -1,4 +1,4 @@
import {debug, info} from '@actions/core'
import {debug, info, warning} from '@actions/core'
import {promises as fs} from 'fs'
import {HttpCodes, HttpClient} from '@actions/http-client'
import {BearerCredentialHandler} from '@actions/http-client/auth'
@@ -302,3 +302,24 @@ export async function createEmptyFilesForArtifact(
await (await fs.open(filePath, 'w')).close()
}
}
export function getProperRetention(
retentionInput: number,
retentionSetting: string | undefined
): number {
if (retentionInput < 0) {
throw new Error('Invalid retention, minimum value is 1.')
}
let retention = retentionInput
if (retentionSetting) {
const maxRetention = parseInt(retentionSetting)
if (!isNaN(maxRetention) && maxRetention < retention) {
warning(
`Retention days is greater than the max value allowed by the repository setting, reduce retention to ${maxRetention} days`
)
retention = maxRetention
}
}
return retention
}