diff --git a/packages/cache/src/cache.ts b/packages/cache/src/cache.ts index f7fadb6f..be7920c9 100644 --- a/packages/cache/src/cache.ts +++ b/packages/cache/src/cache.ts @@ -21,6 +21,14 @@ export class ReserveCacheError extends Error { } } +export class DeleteCacheError extends Error { + constructor(message: string) { + super(message) + this.name = 'DeleteCacheError' + Object.setPrototypeOf(this, DeleteCacheError.prototype) + } +} + function checkPaths(paths: string[]): void { if (!paths || paths.length === 0) { throw new ValidationError( @@ -258,3 +266,44 @@ export async function saveCache( return cacheId } + +/** + * Deletes a cache item with the specified key + * + * @param key an explicit key for the cache to delete + * @param ref only delete items with key for this reference The ref for a branch should be formatted as + * refs/heads/. To reference a pull request use refs/pull//merge. + */ +export async function deleteCacheWithKey( + key: string, + ref?: string +): Promise { + checkKey(key) + + core.debug(`Deleting Cache with key "${key}" and ref "${ref}"`) + const deleteCacheResponse = await cacheHttpClient.deleteCacheWithKey(key, ref) + if (deleteCacheResponse?.statusCode !== 200) { + throw new DeleteCacheError( + `Unable to delete cache with key ${key}. More details: ${deleteCacheResponse?.error?.message}` + ) + } + + return deleteCacheResponse?.result?.totalCount +} + +/** + * Deletes a cache item with the specified id + * + * @param id an explicit id for the cache to delete + */ +export async function deleteCacheWithId(id: number): Promise { + core.debug(`Deleting Cache with id ${id.toString()}`) + const deleteCacheResponse = await cacheHttpClient.deleteCacheWithId(id) + if (deleteCacheResponse?.statusCode !== 204) { + throw new DeleteCacheError( + `Unable to delete cache with id ${id}. More details: ${deleteCacheResponse?.error?.message}` + ) + } + + return deleteCacheResponse?.result?.totalCount +} diff --git a/packages/cache/src/internal/cacheHttpClient.ts b/packages/cache/src/internal/cacheHttpClient.ts index f96ca381..c38506e8 100644 --- a/packages/cache/src/internal/cacheHttpClient.ts +++ b/packages/cache/src/internal/cacheHttpClient.ts @@ -18,7 +18,8 @@ import { ReserveCacheRequest, ReserveCacheResponse, ITypedResponseWithError, - ArtifactCacheList + ArtifactCacheList, + DeleteCacheResponse } from './contracts' import { downloadCacheHttpClient, @@ -227,6 +228,37 @@ export async function reserveCache( return response } +export async function deleteCacheWithKey( + key: string, + ref?: string +): Promise> { + const httpClient = createHttpClient() + + const response = await retryTypedResponse('deleteCache', async () => + httpClient.deleteJson( + ref != null + ? getCacheApiUrl(`caches?key=${key}&ref=${ref}`) + : getCacheApiUrl(`caches?key=${key}`) + ) + ) + + return response +} + +export async function deleteCacheWithId( + id: number +): Promise> { + const httpClient = createHttpClient() + + const response = await retryTypedResponse('deleteCache', async () => + httpClient.deleteJson( + getCacheApiUrl(`caches/${id.toString()}`) + ) + ) + + return response +} + function getContentRange(start: number, end: number): string { // Format: `bytes start-end/filesize // start and end are inclusive diff --git a/packages/cache/src/internal/contracts.d.ts b/packages/cache/src/internal/contracts.d.ts index 6fcd9427..7c00cead 100644 --- a/packages/cache/src/internal/contracts.d.ts +++ b/packages/cache/src/internal/contracts.d.ts @@ -33,6 +33,10 @@ export interface ReserveCacheResponse { cacheId: number } +export interface DeleteCacheResponse { + totalCount: number +} + export interface InternalCacheOptions { compressionMethod?: CompressionMethod enableCrossOsArchive?: boolean diff --git a/packages/http-client/src/index.ts b/packages/http-client/src/index.ts index 6f575f7d..dcbee3e7 100644 --- a/packages/http-client/src/index.ts +++ b/packages/http-client/src/index.ts @@ -336,6 +336,27 @@ export class HttpClient { return this._processResponse(res, this.requestOptions) } + async deleteJson( + requestUrl: string, + additionalHeaders: http.OutgoingHttpHeaders = {} + ): Promise> { + additionalHeaders[Headers.Accept] = this._getExistingOrDefaultHeader( + additionalHeaders, + Headers.Accept, + MediaTypes.ApplicationJson + ) + additionalHeaders[Headers.ContentType] = this._getExistingOrDefaultHeader( + additionalHeaders, + Headers.ContentType, + MediaTypes.ApplicationJson + ) + const res: HttpClientResponse = await this.del( + requestUrl, + additionalHeaders + ) + return this._processResponse(res, this.requestOptions) + } + /** * Makes a raw http request. * All other methods such as get, post, patch, and request ultimately call this.