132 lines
3.9 KiB
TypeScript
132 lines
3.9 KiB
TypeScript
|
|
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();
|