feat(appstore): publish resolver client
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
import { tap, expect } from '@git.zone/tstest/tapbundle';
|
||||
import {
|
||||
AppStoreResolver,
|
||||
parseDockerImageReference,
|
||||
parseServezoneAppStoreManifest,
|
||||
} from '../ts_client/index.js';
|
||||
|
||||
tap.test('parses docker image references', async () => {
|
||||
expect(parseDockerImageReference('nginx:alpine')).toEqual({
|
||||
registry: 'registry-1.docker.io',
|
||||
repository: 'library/nginx',
|
||||
tag: 'alpine',
|
||||
digest: undefined,
|
||||
});
|
||||
expect(parseDockerImageReference('code.foss.global/serve.zone/cloudly:latest')).toEqual({
|
||||
registry: 'code.foss.global',
|
||||
repository: 'serve.zone/cloudly',
|
||||
tag: 'latest',
|
||||
digest: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('validates servezone appstore manifests', async () => {
|
||||
const manifest = parseServezoneAppStoreManifest({
|
||||
schemaVersion: 1,
|
||||
app: {
|
||||
id: 'cloudly',
|
||||
name: 'Cloudly',
|
||||
description: 'Control plane',
|
||||
category: 'Dev Tools',
|
||||
},
|
||||
runtime: {
|
||||
image: 'code.foss.global/serve.zone/cloudly:latest',
|
||||
port: 80,
|
||||
},
|
||||
});
|
||||
|
||||
expect(manifest.app.id).toEqual('cloudly');
|
||||
});
|
||||
|
||||
tap.test('resolves repo manifests and digest tracked images', async () => {
|
||||
const baseUrl = 'https://appstore.example.test';
|
||||
const manifestUrl = 'https://code.example.test/cloudly/servezone.appstore.json';
|
||||
const digest = 'sha256:1234567890abcdef';
|
||||
|
||||
const fakeFetch: typeof fetch = async (inputArg, initArg) => {
|
||||
const url = inputArg instanceof Request ? inputArg.url : inputArg.toString();
|
||||
const method = initArg?.method || 'GET';
|
||||
|
||||
if (url === `${baseUrl}/appstore.resolved.json`) {
|
||||
return new Response('not found', { status: 404 });
|
||||
}
|
||||
|
||||
if (url === `${baseUrl}/appstore.json`) {
|
||||
return Response.json({
|
||||
schemaVersion: 1,
|
||||
updatedAt: '2026-05-25T00:00:00Z',
|
||||
apps: [
|
||||
{
|
||||
id: 'cloudly',
|
||||
name: 'Cloudly',
|
||||
description: 'Curated listing metadata.',
|
||||
category: 'Dev Tools',
|
||||
latestVersion: 'latest',
|
||||
source: {
|
||||
type: 'repoManifest',
|
||||
url: manifestUrl,
|
||||
ref: 'main',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
if (url === manifestUrl) {
|
||||
return Response.json({
|
||||
schemaVersion: 1,
|
||||
app: {
|
||||
id: 'cloudly',
|
||||
name: 'Cloudly',
|
||||
description: 'Manifest-owned metadata.',
|
||||
category: 'Dev Tools',
|
||||
},
|
||||
latestVersion: 'latest',
|
||||
source: {
|
||||
type: 'dockerImage',
|
||||
image: 'registry.example.test/serve.zone/cloudly:latest',
|
||||
tracking: 'digest',
|
||||
},
|
||||
runtime: {
|
||||
image: 'registry.example.test/serve.zone/cloudly:latest',
|
||||
port: 80,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
url === 'https://registry.example.test/v2/serve.zone/cloudly/manifests/latest' &&
|
||||
method === 'HEAD'
|
||||
) {
|
||||
return new Response(null, {
|
||||
status: 200,
|
||||
headers: { 'docker-content-digest': digest },
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(`unexpected ${method} ${url}`, { status: 500 });
|
||||
};
|
||||
|
||||
const resolver = new AppStoreResolver({
|
||||
baseUrl,
|
||||
fetch: fakeFetch,
|
||||
now: () => new Date('2026-05-25T12:00:00Z'),
|
||||
});
|
||||
|
||||
const appStore = await resolver.getAppStoreIndex();
|
||||
expect(appStore.apps[0].latestVersion).toEqual(`latest@${digest}`);
|
||||
expect(appStore.apps[0].resolvedSource?.manifestHash?.length).toEqual(64);
|
||||
expect(appStore.apps[0].upgradeStrategy).toEqual('dockerDigest');
|
||||
|
||||
const appMeta = await resolver.getAppMeta('cloudly');
|
||||
expect(appMeta.latestVersion).toEqual(`latest@${digest}`);
|
||||
expect(appMeta.versions).toEqual([`latest@${digest}`]);
|
||||
|
||||
const config = await resolver.getAppVersionConfig('cloudly', appMeta.latestVersion);
|
||||
expect(config.image).toEqual('registry.example.test/serve.zone/cloudly:latest');
|
||||
expect(config.appStoreVersion).toEqual(`latest@${digest}`);
|
||||
expect(config.resolvedImageDigest).toEqual(digest);
|
||||
});
|
||||
|
||||
export default tap.start();
|
||||
Reference in New Issue
Block a user