proxy support (#166)
* Replace typed rest client with new http-client * Send Content-Type: application/json and fix up some types * Lint * Consume @actions/http-client:1.0.5 * Consume @actions/http-client:1.0.6 * Dont send headers manually, http-client automatically will
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -94,3 +94,6 @@ typings/ | |||||||
|  |  | ||||||
| # DynamoDB Local files | # DynamoDB Local files | ||||||
| .dynamodb/ | .dynamodb/ | ||||||
|  |  | ||||||
|  | # Text editor files | ||||||
|  | .vscode/ | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										28
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -14,6 +14,14 @@ | |||||||
|       "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.1.tgz", |       "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.0.1.tgz", | ||||||
|       "integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ==" |       "integrity": "sha512-nvFkxwiicvpzNiCBF4wFBDfnBvi7xp/as7LE1hBxBxKG2L29+gkIPBiLKMVORL+Hg3JNf07AKRfl0V5djoypjQ==" | ||||||
|     }, |     }, | ||||||
|  |     "@actions/http-client": { | ||||||
|  |       "version": "1.0.6", | ||||||
|  |       "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-1.0.6.tgz", | ||||||
|  |       "integrity": "sha512-LGmio4w98UyGX33b/W6V6Nx/sQHRXZ859YlMkn36wPsXPB82u8xTVlA/Dq2DXrm6lEq9RVmisRJa1c+HETAIJA==", | ||||||
|  |       "requires": { | ||||||
|  |         "tunnel": "0.0.6" | ||||||
|  |       } | ||||||
|  |     }, | ||||||
|     "@actions/io": { |     "@actions/io": { | ||||||
|       "version": "1.0.1", |       "version": "1.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.1.tgz", |       "resolved": "https://registry.npmjs.org/@actions/io/-/io-1.0.1.tgz", | ||||||
| @ -5933,9 +5941,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "tunnel": { |     "tunnel": { | ||||||
|       "version": "0.0.4", |       "version": "0.0.6", | ||||||
|       "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.4.tgz", |       "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", | ||||||
|       "integrity": "sha1-LTeFoVjBdMmhbcLARuxfxfF0IhM=" |       "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==" | ||||||
|     }, |     }, | ||||||
|     "tunnel-agent": { |     "tunnel-agent": { | ||||||
|       "version": "0.6.0", |       "version": "0.6.0", | ||||||
| @ -5973,15 +5981,6 @@ | |||||||
|       "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", |       "integrity": "sha512-DWkS49EQKVX//Tbupb9TFa19c7+MK1XmzkrZUR8TAktmE/DizXoaoJV6TZ/tSIPXipqNiRI6CyAe7x69Jb6RSw==", | ||||||
|       "dev": true |       "dev": true | ||||||
|     }, |     }, | ||||||
|     "typed-rest-client": { |  | ||||||
|       "version": "1.5.0", |  | ||||||
|       "resolved": "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.5.0.tgz", |  | ||||||
|       "integrity": "sha512-DVZRlmsfnTjp6ZJaatcdyvvwYwbWvR4YDNFDqb+qdTxpvaVP99YCpBkA8rxsLtAPjBVoDe4fNsnMIdZTiPuKWg==", |  | ||||||
|       "requires": { |  | ||||||
|         "tunnel": "0.0.4", |  | ||||||
|         "underscore": "1.8.3" |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|     "typescript": { |     "typescript": { | ||||||
|       "version": "3.7.3", |       "version": "3.7.3", | ||||||
|       "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", |       "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", | ||||||
| @ -5999,11 +5998,6 @@ | |||||||
|         "source-map": "~0.6.1" |         "source-map": "~0.6.1" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "underscore": { |  | ||||||
|       "version": "1.8.3", |  | ||||||
|       "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz", |  | ||||||
|       "integrity": "sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=" |  | ||||||
|     }, |  | ||||||
|     "union-value": { |     "union-value": { | ||||||
|       "version": "1.0.1", |       "version": "1.0.1", | ||||||
|       "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", |       "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", | ||||||
|  | |||||||
| @ -26,8 +26,8 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@actions/core": "^1.2.0", |     "@actions/core": "^1.2.0", | ||||||
|     "@actions/exec": "^1.0.1", |     "@actions/exec": "^1.0.1", | ||||||
|  |     "@actions/http-client": "^1.0.6", | ||||||
|     "@actions/io": "^1.0.1", |     "@actions/io": "^1.0.1", | ||||||
|     "typed-rest-client": "^1.5.0", |  | ||||||
|     "uuid": "^3.3.3" |     "uuid": "^3.3.3" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|  | |||||||
| @ -1,13 +1,12 @@ | |||||||
| import * as core from "@actions/core"; | import * as core from "@actions/core"; | ||||||
| import * as fs from "fs"; | import * as fs from "fs"; | ||||||
| import { BearerCredentialHandler } from "typed-rest-client/Handlers"; | import { BearerCredentialHandler } from "@actions/http-client/auth"; | ||||||
| import { HttpClient, HttpCodes } from "typed-rest-client/HttpClient"; | import { HttpClient, HttpCodes } from "@actions/http-client"; | ||||||
| import { IHttpClientResponse } from "typed-rest-client/Interfaces"; |  | ||||||
| import { | import { | ||||||
|  |     IHttpClientResponse, | ||||||
|     IRequestOptions, |     IRequestOptions, | ||||||
|     RestClient, |     ITypedResponse | ||||||
|     IRestResponse | } from "@actions/http-client/interfaces"; | ||||||
| } from "typed-rest-client/RestClient"; |  | ||||||
| import { | import { | ||||||
|     ArtifactCacheEntry, |     ArtifactCacheEntry, | ||||||
|     CommitCacheRequest, |     CommitCacheRequest, | ||||||
| @ -16,11 +15,17 @@ import { | |||||||
| } from "./contracts"; | } from "./contracts"; | ||||||
| import * as utils from "./utils/actionUtils"; | import * as utils from "./utils/actionUtils"; | ||||||
|  |  | ||||||
| function isSuccessStatusCode(statusCode: number): boolean { | function isSuccessStatusCode(statusCode?: number): boolean { | ||||||
|  |     if (!statusCode) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|     return statusCode >= 200 && statusCode < 300; |     return statusCode >= 200 && statusCode < 300; | ||||||
| } | } | ||||||
|  |  | ||||||
| function isRetryableStatusCode(statusCode: number): boolean { | function isRetryableStatusCode(statusCode?: number): boolean { | ||||||
|  |     if (!statusCode) { | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|     const retryableStatusCodes = [ |     const retryableStatusCodes = [ | ||||||
|         HttpCodes.BadGateway, |         HttpCodes.BadGateway, | ||||||
|         HttpCodes.ServiceUnavailable, |         HttpCodes.ServiceUnavailable, | ||||||
| @ -29,7 +34,7 @@ function isRetryableStatusCode(statusCode: number): boolean { | |||||||
|     return retryableStatusCodes.includes(statusCode); |     return retryableStatusCodes.includes(statusCode); | ||||||
| } | } | ||||||
|  |  | ||||||
| function getCacheApiUrl(): string { | function getCacheApiUrl(resource: string): string { | ||||||
|     // Ideally we just use ACTIONS_CACHE_URL |     // Ideally we just use ACTIONS_CACHE_URL | ||||||
|     const baseUrl: string = ( |     const baseUrl: string = ( | ||||||
|         process.env["ACTIONS_CACHE_URL"] || |         process.env["ACTIONS_CACHE_URL"] || | ||||||
| @ -42,8 +47,9 @@ function getCacheApiUrl(): string { | |||||||
|         ); |         ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     core.debug(`Cache Url: ${baseUrl}`); |     const url = `${baseUrl}_apis/artifactcache/${resource}`; | ||||||
|     return `${baseUrl}_apis/artifactcache/`; |     core.debug(`Resource Url: ${url}`); | ||||||
|  |     return url; | ||||||
| } | } | ||||||
|  |  | ||||||
| function createAcceptHeader(type: string, apiVersion: string): string { | function createAcceptHeader(type: string, apiVersion: string): string { | ||||||
| @ -52,30 +58,33 @@ function createAcceptHeader(type: string, apiVersion: string): string { | |||||||
|  |  | ||||||
| function getRequestOptions(): IRequestOptions { | function getRequestOptions(): IRequestOptions { | ||||||
|     const requestOptions: IRequestOptions = { |     const requestOptions: IRequestOptions = { | ||||||
|         acceptHeader: createAcceptHeader("application/json", "6.0-preview.1") |         headers: { | ||||||
|  |             Accept: createAcceptHeader("application/json", "6.0-preview.1") | ||||||
|  |         } | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     return requestOptions; |     return requestOptions; | ||||||
| } | } | ||||||
|  |  | ||||||
| function createRestClient(): RestClient { | function createHttpClient(): HttpClient { | ||||||
|     const token = process.env["ACTIONS_RUNTIME_TOKEN"] || ""; |     const token = process.env["ACTIONS_RUNTIME_TOKEN"] || ""; | ||||||
|     const bearerCredentialHandler = new BearerCredentialHandler(token); |     const bearerCredentialHandler = new BearerCredentialHandler(token); | ||||||
|  |  | ||||||
|     return new RestClient("actions/cache", getCacheApiUrl(), [ |     return new HttpClient( | ||||||
|         bearerCredentialHandler |         "actions/cache", | ||||||
|     ]); |         [bearerCredentialHandler], | ||||||
|  |         getRequestOptions() | ||||||
|  |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
| export async function getCacheEntry( | export async function getCacheEntry( | ||||||
|     keys: string[] |     keys: string[] | ||||||
| ): Promise<ArtifactCacheEntry | null> { | ): Promise<ArtifactCacheEntry | null> { | ||||||
|     const restClient = createRestClient(); |     const httpClient = createHttpClient(); | ||||||
|     const resource = `cache?keys=${encodeURIComponent(keys.join(","))}`; |     const resource = `cache?keys=${encodeURIComponent(keys.join(","))}`; | ||||||
|  |  | ||||||
|     const response = await restClient.get<ArtifactCacheEntry>( |     const response = await httpClient.getJson<ArtifactCacheEntry>( | ||||||
|         resource, |         getCacheApiUrl(resource) | ||||||
|         getRequestOptions() |  | ||||||
|     ); |     ); | ||||||
|     if (response.statusCode === 204) { |     if (response.statusCode === 204) { | ||||||
|         return null; |         return null; | ||||||
| @ -83,6 +92,7 @@ export async function getCacheEntry( | |||||||
|     if (!isSuccessStatusCode(response.statusCode)) { |     if (!isSuccessStatusCode(response.statusCode)) { | ||||||
|         throw new Error(`Cache service responded with ${response.statusCode}`); |         throw new Error(`Cache service responded with ${response.statusCode}`); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const cacheResult = response.result; |     const cacheResult = response.result; | ||||||
|     const cacheDownloadUrl = cacheResult?.archiveLocation; |     const cacheDownloadUrl = cacheResult?.archiveLocation; | ||||||
|     if (!cacheDownloadUrl) { |     if (!cacheDownloadUrl) { | ||||||
| @ -118,17 +128,15 @@ export async function downloadCache( | |||||||
|  |  | ||||||
| // Reserve Cache | // Reserve Cache | ||||||
| export async function reserveCache(key: string): Promise<number> { | export async function reserveCache(key: string): Promise<number> { | ||||||
|     const restClient = createRestClient(); |     const httpClient = createHttpClient(); | ||||||
|  |  | ||||||
|     const reserveCacheRequest: ReserveCacheRequest = { |     const reserveCacheRequest: ReserveCacheRequest = { | ||||||
|         key |         key | ||||||
|     }; |     }; | ||||||
|     const response = await restClient.create<ReserveCacheResponse>( |     const response = await httpClient.postJson<ReserveCacheResponse>( | ||||||
|         "caches", |         getCacheApiUrl("caches"), | ||||||
|         reserveCacheRequest, |         reserveCacheRequest | ||||||
|         getRequestOptions() |  | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
|     return response?.result?.cacheId ?? -1; |     return response?.result?.cacheId ?? -1; | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -142,7 +150,7 @@ function getContentRange(start: number, end: number): string { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function uploadChunk( | async function uploadChunk( | ||||||
|     restClient: RestClient, |     httpClient: HttpClient, | ||||||
|     resourceUrl: string, |     resourceUrl: string, | ||||||
|     data: NodeJS.ReadableStream, |     data: NodeJS.ReadableStream, | ||||||
|     start: number, |     start: number, | ||||||
| @ -156,38 +164,37 @@ async function uploadChunk( | |||||||
|             end |             end | ||||||
|         )}` |         )}` | ||||||
|     ); |     ); | ||||||
|     const requestOptions = getRequestOptions(); |     const additionalHeaders = { | ||||||
|     requestOptions.additionalHeaders = { |  | ||||||
|         "Content-Type": "application/octet-stream", |         "Content-Type": "application/octet-stream", | ||||||
|         "Content-Range": getContentRange(start, end) |         "Content-Range": getContentRange(start, end) | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const uploadChunkRequest = async (): Promise<IRestResponse<void>> => { |     const uploadChunkRequest = async (): Promise<IHttpClientResponse> => { | ||||||
|         return await restClient.uploadStream<void>( |         return await httpClient.sendStream( | ||||||
|             "PATCH", |             "PATCH", | ||||||
|             resourceUrl, |             resourceUrl, | ||||||
|             data, |             data, | ||||||
|             requestOptions |             additionalHeaders | ||||||
|         ); |         ); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|     const response = await uploadChunkRequest(); |     const response = await uploadChunkRequest(); | ||||||
|     if (isSuccessStatusCode(response.statusCode)) { |     if (isSuccessStatusCode(response.message.statusCode)) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (isRetryableStatusCode(response.statusCode)) { |     if (isRetryableStatusCode(response.message.statusCode)) { | ||||||
|         core.debug( |         core.debug( | ||||||
|             `Received ${response.statusCode}, retrying chunk at offset ${start}.` |             `Received ${response.message.statusCode}, retrying chunk at offset ${start}.` | ||||||
|         ); |         ); | ||||||
|         const retryResponse = await uploadChunkRequest(); |         const retryResponse = await uploadChunkRequest(); | ||||||
|         if (isSuccessStatusCode(retryResponse.statusCode)) { |         if (isSuccessStatusCode(retryResponse.message.statusCode)) { | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     throw new Error( |     throw new Error( | ||||||
|         `Cache service responded with ${response.statusCode} during chunk upload.` |         `Cache service responded with ${response.message.statusCode} during chunk upload.` | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -200,13 +207,13 @@ function parseEnvNumber(key: string): number | undefined { | |||||||
| } | } | ||||||
|  |  | ||||||
| async function uploadFile( | async function uploadFile( | ||||||
|     restClient: RestClient, |     httpClient: HttpClient, | ||||||
|     cacheId: number, |     cacheId: number, | ||||||
|     archivePath: string |     archivePath: string | ||||||
| ): Promise<void> { | ): Promise<void> { | ||||||
|     // Upload Chunks |     // Upload Chunks | ||||||
|     const fileSize = fs.statSync(archivePath).size; |     const fileSize = fs.statSync(archivePath).size; | ||||||
|     const resourceUrl = getCacheApiUrl() + "caches/" + cacheId.toString(); |     const resourceUrl = getCacheApiUrl(`caches/${cacheId.toString()}`); | ||||||
|     const fd = fs.openSync(archivePath, "r"); |     const fd = fs.openSync(archivePath, "r"); | ||||||
|  |  | ||||||
|     const concurrency = parseEnvNumber("CACHE_UPLOAD_CONCURRENCY") ?? 4; // # of HTTP requests in parallel |     const concurrency = parseEnvNumber("CACHE_UPLOAD_CONCURRENCY") ?? 4; // # of HTTP requests in parallel | ||||||
| @ -237,7 +244,7 @@ async function uploadFile( | |||||||
|                     }); |                     }); | ||||||
|  |  | ||||||
|                     await uploadChunk( |                     await uploadChunk( | ||||||
|                         restClient, |                         httpClient, | ||||||
|                         resourceUrl, |                         resourceUrl, | ||||||
|                         chunk, |                         chunk, | ||||||
|                         start, |                         start, | ||||||
| @ -253,16 +260,14 @@ async function uploadFile( | |||||||
| } | } | ||||||
|  |  | ||||||
| async function commitCache( | async function commitCache( | ||||||
|     restClient: RestClient, |     httpClient: HttpClient, | ||||||
|     cacheId: number, |     cacheId: number, | ||||||
|     filesize: number |     filesize: number | ||||||
| ): Promise<IRestResponse<void>> { | ): Promise<ITypedResponse<null>> { | ||||||
|     const requestOptions = getRequestOptions(); |  | ||||||
|     const commitCacheRequest: CommitCacheRequest = { size: filesize }; |     const commitCacheRequest: CommitCacheRequest = { size: filesize }; | ||||||
|     return await restClient.create( |     return await httpClient.postJson<null>( | ||||||
|         `caches/${cacheId.toString()}`, |         getCacheApiUrl(`caches/${cacheId.toString()}`), | ||||||
|         commitCacheRequest, |         commitCacheRequest | ||||||
|         requestOptions |  | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -270,16 +275,16 @@ export async function saveCache( | |||||||
|     cacheId: number, |     cacheId: number, | ||||||
|     archivePath: string |     archivePath: string | ||||||
| ): Promise<void> { | ): Promise<void> { | ||||||
|     const restClient = createRestClient(); |     const httpClient = createHttpClient(); | ||||||
|  |  | ||||||
|     core.debug("Upload cache"); |     core.debug("Upload cache"); | ||||||
|     await uploadFile(restClient, cacheId, archivePath); |     await uploadFile(httpClient, cacheId, archivePath); | ||||||
|  |  | ||||||
|     // Commit Cache |     // Commit Cache | ||||||
|     core.debug("Commiting cache"); |     core.debug("Commiting cache"); | ||||||
|     const cacheSize = utils.getArchiveFileSize(archivePath); |     const cacheSize = utils.getArchiveFileSize(archivePath); | ||||||
|     const commitCacheResponse = await commitCache( |     const commitCacheResponse = await commitCache( | ||||||
|         restClient, |         httpClient, | ||||||
|         cacheId, |         cacheId, | ||||||
|         cacheSize |         cacheSize | ||||||
|     ); |     ); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 David Kale
					David Kale