feat: add CI deployment and live progress
This commit is contained in:
+44
-2
@@ -21,8 +21,18 @@ export type RegistryResolveOptions = {
|
||||
credentials?: RegistryCredentials;
|
||||
insecure?: boolean;
|
||||
origin?: string;
|
||||
cacheTtlMs?: number;
|
||||
cacheMaxEntries?: number;
|
||||
clock?: () => number;
|
||||
};
|
||||
|
||||
const DEFAULT_DIGEST_CACHE_TTL_MS = 30_000;
|
||||
const DEFAULT_DIGEST_CACHE_MAX_ENTRIES = 256;
|
||||
const digestCache = new Map<
|
||||
string,
|
||||
{ digest: Sha256Digest; expiresAt: number }
|
||||
>();
|
||||
|
||||
export type ParsedImageReference = {
|
||||
registry: string;
|
||||
repository: string;
|
||||
@@ -106,6 +116,13 @@ export async function resolveRegistryDigest(
|
||||
): Promise<Sha256Digest> {
|
||||
const parsed = parseImageReference(image);
|
||||
if (parsed.digest) return parsed.digest;
|
||||
const now = options.clock ?? Date.now;
|
||||
const cacheTtlMs = Number.isFinite(options.cacheTtlMs)
|
||||
? Math.max(0, options.cacheTtlMs!)
|
||||
: DEFAULT_DIGEST_CACHE_TTL_MS;
|
||||
const cacheMaxEntries = Number.isFinite(options.cacheMaxEntries)
|
||||
? Math.max(0, Math.floor(options.cacheMaxEntries!))
|
||||
: DEFAULT_DIGEST_CACHE_MAX_ENTRIES;
|
||||
const fetcher: RegistryFetch = options.fetch ?? globalThis.fetch;
|
||||
const scheme = options.insecure ? "http" : "https";
|
||||
const repository = parsed.repository
|
||||
@@ -116,6 +133,19 @@ export async function resolveRegistryDigest(
|
||||
/\/+$/,
|
||||
"",
|
||||
);
|
||||
const credentialsKey = options.credentials
|
||||
? createHash("sha256")
|
||||
.update(
|
||||
`${options.credentials.username}\0${options.credentials.password}`,
|
||||
)
|
||||
.digest("hex")
|
||||
: "anonymous";
|
||||
const cacheKey = `${origin}\0${parsed.repository}\0${parsed.reference}\0${credentialsKey}`;
|
||||
const cached = digestCache.get(cacheKey);
|
||||
if (cached) {
|
||||
if (cached.expiresAt > now()) return cached.digest;
|
||||
digestCache.delete(cacheKey);
|
||||
}
|
||||
const manifestUrl = `${origin}/v2/${repository}/manifests/${encodeURIComponent(parsed.reference)}`;
|
||||
const headers = new Headers({ accept: ACCEPT });
|
||||
if (options.credentials) {
|
||||
@@ -167,9 +197,21 @@ export async function resolveRegistryDigest(
|
||||
.get("docker-content-digest")
|
||||
?.trim()
|
||||
?.toLowerCase();
|
||||
let digest: Sha256Digest;
|
||||
if (advertised !== undefined) {
|
||||
assertSha256Digest(advertised);
|
||||
return advertised;
|
||||
digest = advertised;
|
||||
} else {
|
||||
digest = `sha256:${createHash("sha256").update(body).digest("hex")}`;
|
||||
}
|
||||
return `sha256:${createHash("sha256").update(body).digest("hex")}`;
|
||||
if (cacheTtlMs && cacheMaxEntries) {
|
||||
digestCache.delete(cacheKey);
|
||||
while (digestCache.size >= cacheMaxEntries)
|
||||
digestCache.delete(digestCache.keys().next().value!);
|
||||
digestCache.set(cacheKey, {
|
||||
digest,
|
||||
expiresAt: now() + cacheTtlMs,
|
||||
});
|
||||
}
|
||||
return digest;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user