Index

src/cli/pr-artifact-cleaner.ts

ageInDays
Type : number
Default value : programOptions.durationKept
authHeader
Default value : programOptions.basicAuth ? { Authorization: `Basic ${programOptions.basicAuth as string}` } : { 'X-JFrog-Art-Api': programOptions.apiKey as string }
fetchOptions
Default value : { method: 'POST', headers: authHeader, body: `items.find( { "$and": [ {"repo": {"$eq":"${repository}"}}, {"path":{"$match":"${path}"}}, {"created":{"$before":"${ageInDays}d"}} ] } ).include("name","repo","path","created") .sort({"$desc" : ["path","name"]}) .limit(10000)` } as const satisfies RequestInit
logger
Default value : winston.createLogger({ level: programOptions.verbose ? 'debug' : 'info', format: winston.format.simple(), transports: [ new winston.transports.Console(winstonOptions.console) ] })
path
Type : string
Default value : programOptions.path
prBuilds
Type : number
Default value : programOptions.prBuilds
programOptions
Default value : program.opts()
repository
Type : string
Default value : programOptions.repository
run
Default value : async () => { logger.info(`Requesting old artifacts using ${url}`); let responseSearch: any; let responseSearchObj: { results: { repo: string; path: string; name: string }[] }; try { responseSearch = await fetch(url, fetchOptions); responseSearchObj = await responseSearch.json(); } catch (e) { logger.warn('No result found %o', e); process.exit(0); } /** uris will contain the list of all artifacts that need to be deleted */ const mapOfKeptItems = new Map<string, number[]>(); const mapOfKeptResult = new Map<string, { repo: string; path: string; name: string }[]>(); const resultToDelete: { repo: string; path: string; name: string }[] = []; const sortedResult = responseSearchObj.results.sort((a, b) => b.name.localeCompare(a.name)); for (const result of sortedResult) { const splitPath = result.name.split('.'); const mapId = splitPath.slice(0, -2).join('.'); const currentBuildNumber = +splitPath.at(-2)!; const buildNumbers = mapOfKeptItems.get(mapId); if (buildNumbers) { buildNumbers.sort(); let isBuildNumberAlreadyInMap = false; let isBuildNumberHigherThanExisting = true; buildNumbers.forEach((value) => { isBuildNumberAlreadyInMap = isBuildNumberAlreadyInMap || (value === currentBuildNumber); isBuildNumberHigherThanExisting = isBuildNumberHigherThanExisting && (value < currentBuildNumber); }); if (!isBuildNumberAlreadyInMap) { if (buildNumbers.length >= prBuilds && !isBuildNumberHigherThanExisting) { resultToDelete.push(result); } else { if (buildNumbers.length >= prBuilds && isBuildNumberHigherThanExisting) { const buildNumberToRemove = buildNumbers.shift(); if (buildNumberToRemove) { const resultsToRemove = mapOfKeptResult.get(`${mapId}${buildNumberToRemove}`); if (resultsToRemove) { resultToDelete.push(...resultsToRemove); } } } buildNumbers.push(currentBuildNumber); buildNumbers.sort(); mapOfKeptItems.set(mapId, buildNumbers); const keptBuildNumbers = mapOfKeptResult.get(`${mapId}${currentBuildNumber}`); if (keptBuildNumbers) { keptBuildNumbers.push(result); mapOfKeptResult.set(`${mapId}${currentBuildNumber}`, keptBuildNumbers); } else { mapOfKeptResult.set(`${mapId}${currentBuildNumber}`, [result]); } } } } else { mapOfKeptItems.set(mapId, [currentBuildNumber]); } } logger.debug('Map of build that will be kept: %o', mapOfKeptItems); const filesToDelete = resultToDelete.map( (data) => (programOptions.artifactoryUrl as string) + (programOptions.artifactoryUrl.endsWith('/') ? '' : '/') + repository + '/' + data.path + '/' + data.name ); for (const uri of filesToDelete) { logger.info(`Deleting ${uri}...`); if (!programOptions.dryRun) { const response = await fetch(uri, { method: 'DELETE', headers: authHeader }); logger.info(response); } } }
url
Type : string
Default value : programOptions.artifactoryUrl
winstonOptions
Type : object
Default value : { console: { format: winston.format.combine( winston.format.prettyPrint(), winston.format.splat(), winston.format.printf((info) => { if (typeof info.message === 'object') { info.message = JSON.stringify(info.message, null, 3); } return info.message as string; }) ) } }

src/cli/artifact-cleaner.ts

limitTimestampToKeepOldArtifact
Default value : Date.now() - opts.durationKept
logger
Default value : winston.createLogger({ level: opts.verbose ? 'debug' : 'info', format: winston.format.simple(), transports: new winston.transports.Console() })
matchFilter
Default value : (fullUrl: string, types: string[]) => { for (const type of types) { if (fullUrl.endsWith(type)) { return true; } } logger.info(`${fullUrl} dropped because it doesn't match any of the patterns`); return false; }

Returns true if the url match one of the artifact types

options
Default value : { headers: { Authorization: 'Basic ' + (opts.basicAuth as string) } } as const satisfies RequestInit
opts
Default value : program.opts()
run
Default value : async () => { logger.info(`Requesting old artifacts using ${url}`); let responseSearch; let responseSearchObj: { results: { uri: string }[] }; try { responseSearch = await fetch(url, options); responseSearchObj = await responseSearch.json(); } catch (e) { logger.warn('No result found ', e); process.exit(0); } /** uris will contain the list of all artifacts that need to be deleted */ const uris = responseSearchObj.results .map((res) => res.uri) .filter((uri) => matchFilter(uri, opts.typeFilter)) .map((uri) => uri.replace('/api/storage', '')); for (const uri of uris) { logger.info(`Deleting ${uri}...`); if (!opts.dryRun) { const response = await fetch(uri, { ...options, method: 'DELETE' }); logger.info(response); } } }
url
Default value : opts.artifactoryUrl as string

results matching ""

    No results matching ""