GitHub(nextgroup2706/ken_nogi)は今後使わず自社Gitea運用に切替え。 NodeSrvは旧リポジトリの履歴を破棄しファイルのみ統合(Dokploy用サービスアカウントは 別途mygit-admin/NodeSrv.gitに履歴あり)。notepmエクスポート(12GB)とPleasanter インストーラzip(208MB)はサイズが大きいため.gitignoreで除外。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
165 lines
6.2 KiB
JavaScript
165 lines
6.2 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
|
|
function withMockFetch(mockFetch, fn) {
|
|
const original = global.fetch;
|
|
global.fetch = mockFetch;
|
|
return fn().finally(() => {
|
|
global.fetch = original;
|
|
});
|
|
}
|
|
|
|
test('trpcGet wraps params in {json:} and unwraps result.data.json', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { trpcGet } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async (url, options) => {
|
|
const parsed = new URL(url);
|
|
assert.strictEqual(parsed.pathname, '/api/trpc/environment.one');
|
|
const input = JSON.parse(parsed.searchParams.get('input'));
|
|
assert.deepStrictEqual(input, { json: { environmentId: 'env-1' } });
|
|
assert.strictEqual(options.headers['x-api-key'], 'test-key');
|
|
return {
|
|
ok: true,
|
|
json: async () => ({ result: { data: { json: { hello: 'world' } } } }),
|
|
};
|
|
}, async () => {
|
|
const result = await trpcGet('environment.one', { environmentId: 'env-1' });
|
|
assert.deepStrictEqual(result, { hello: 'world' });
|
|
});
|
|
});
|
|
|
|
test('trpcPost wraps data in {json:} in the request body', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { trpcPost } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async (url, options) => {
|
|
const parsed = new URL(url);
|
|
assert.strictEqual(parsed.pathname, '/api/trpc/compose.start');
|
|
assert.deepStrictEqual(JSON.parse(options.body), { json: { composeId: 'c1' } });
|
|
assert.strictEqual(options.method, 'POST');
|
|
return {
|
|
ok: true,
|
|
json: async () => ({ result: { data: { json: { success: true } } } }),
|
|
};
|
|
}, async () => {
|
|
const result = await trpcPost('compose.start', { composeId: 'c1' });
|
|
assert.deepStrictEqual(result, { success: true });
|
|
});
|
|
});
|
|
|
|
test('trpcGet throws when the response is not ok', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { trpcGet } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async () => ({ ok: false, status: 400 }), async () => {
|
|
await assert.rejects(() => trpcGet('compose.one', { composeId: 'c1' }), /400/);
|
|
});
|
|
});
|
|
|
|
test('listComposes returns the compose array from environment.one', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { listComposes } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async () => ({
|
|
ok: true,
|
|
json: async () => ({
|
|
result: { data: { json: { compose: [{ composeId: 'c1', name: 'auth-redirect', composeStatus: 'done' }] } } },
|
|
}),
|
|
}), async () => {
|
|
const composes = await listComposes('env-1');
|
|
assert.deepStrictEqual(composes, [{ composeId: 'c1', name: 'auth-redirect', composeStatus: 'done' }]);
|
|
});
|
|
});
|
|
|
|
test('getComposeEnv only returns env and appName, never leaks gitea/github credentials', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { getComposeEnv } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async () => ({
|
|
ok: true,
|
|
json: async () => ({
|
|
result: {
|
|
data: {
|
|
json: {
|
|
composeId: 'c1',
|
|
appName: 'auth-redirect-uzt5hx',
|
|
env: 'PORTAL_APP_TYPE=web\nPORTAL_APP_URL=https://x.apps.next-hd.net',
|
|
gitea: { clientSecret: 'SHOULD_NOT_LEAK', accessToken: 'SHOULD_NOT_LEAK_EITHER' },
|
|
deployments: [{ title: 'irrelevant' }],
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
}), async () => {
|
|
const result = await getComposeEnv('c1');
|
|
assert.deepStrictEqual(Object.keys(result).sort(), ['appName', 'env']);
|
|
assert.strictEqual(result.appName, 'auth-redirect-uzt5hx');
|
|
assert.ok(result.env.includes('PORTAL_APP_TYPE=web'));
|
|
assert.ok(!JSON.stringify(result).includes('SHOULD_NOT_LEAK'));
|
|
});
|
|
});
|
|
|
|
test('getContainers calls docker.getContainersByAppNameMatch with appType docker-compose', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { getContainers } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async (url) => {
|
|
const parsed = new URL(url);
|
|
assert.strictEqual(parsed.pathname, '/api/trpc/docker.getContainersByAppNameMatch');
|
|
const input = JSON.parse(parsed.searchParams.get('input'));
|
|
assert.deepStrictEqual(input, { json: { appName: 'auth-redirect-uzt5hx', appType: 'docker-compose' } });
|
|
return {
|
|
ok: true,
|
|
json: async () => ({ result: { data: { json: [{ containerId: 'abc123', state: 'running' }] } } }),
|
|
};
|
|
}, async () => {
|
|
const containers = await getContainers('auth-redirect-uzt5hx');
|
|
assert.deepStrictEqual(containers, [{ containerId: 'abc123', state: 'running' }]);
|
|
});
|
|
});
|
|
|
|
test('readLogs passes composeId, containerId and tail through', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { readLogs } = require('../src/dokployClient');
|
|
|
|
await withMockFetch(async (url) => {
|
|
const parsed = new URL(url);
|
|
const input = JSON.parse(parsed.searchParams.get('input'));
|
|
assert.deepStrictEqual(input, { json: { composeId: 'c1', containerId: 'abc123', tail: 200 } });
|
|
return { ok: true, json: async () => ({ result: { data: { json: 'log line\n' } } }) };
|
|
}, async () => {
|
|
const logs = await readLogs('c1', 'abc123', 200);
|
|
assert.strictEqual(logs, 'log line\n');
|
|
});
|
|
});
|
|
|
|
test('startCompose/stopCompose/restartContainer POST to the right endpoints', async () => {
|
|
process.env.DOKPLOY_URL = 'https://dokploy.test';
|
|
process.env.DOKPLOY_API_KEY = 'test-key';
|
|
const { startCompose, stopCompose, restartContainer } = require('../src/dokployClient');
|
|
const calledEndpoints = [];
|
|
|
|
await withMockFetch(async (url) => {
|
|
calledEndpoints.push(new URL(url).pathname);
|
|
return { ok: true, json: async () => ({ result: { data: { json: { success: true } } } }) };
|
|
}, async () => {
|
|
await startCompose('c1');
|
|
await stopCompose('c1');
|
|
await restartContainer('abc123');
|
|
});
|
|
|
|
assert.deepStrictEqual(calledEndpoints, [
|
|
'/api/trpc/compose.start',
|
|
'/api/trpc/compose.stop',
|
|
'/api/trpc/docker.restartContainer',
|
|
]);
|
|
});
|