feat(sdk): use config file as single source of truth, remove env var fallbacks (#19409)
## Summary - **Config as source of truth**: `~/.twenty/config.json` is now the single source of truth for SDK authentication — env var fallbacks have been removed from the config resolution chain. - **Test instance support**: `twenty server start --test` spins up a dedicated Docker instance on port 2021 with its own config (`config.test.json`), so integration tests don't interfere with the dev environment. - **API key auth for marketplace**: Removed `UserAuthGuard` from `MarketplaceResolver` so API key tokens (workspace-scoped) can call `installMarketplaceApp`. - **CI for example apps**: Added monorepo CI workflows for `hello-world` and `postcard` example apps to catch regressions. - **Simplified CI**: All `ci-create-app-e2e` and example app workflows now use a shared `spawn-twenty-app-dev-test` action (Docker-based) instead of building the server from source. Consolidated auth env vars to `TWENTY_API_URL` + `TWENTY_API_KEY`. - **Template publishing fix**: `create-twenty-app` template now correctly preserves `.github/` and `.gitignore` through npm publish (stored without leading dot, renamed after copy). ## Test plan - [x] CI SDK (lint, typecheck, unit, integration, e2e) — all green - [x] CI Example App Hello World — green - [x] CI Example App Postcard — green - [x] CI Create App E2E minimal — green - [x] CI Front, CI Server, CI Shared — green
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
import axios from 'axios';
|
||||
import { SERVER_URL } from '@/cli/__tests__/constants/server-url.constant';
|
||||
import { getServerUrl } from '@/cli/__tests__/constants/server-url.constant';
|
||||
|
||||
describe('Twenty Server Health Check (E2E)', () => {
|
||||
const HEALTH_ENDPOINT = `${SERVER_URL}/healthz`;
|
||||
let healthEndpoint: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const serverUrl = await getServerUrl();
|
||||
|
||||
healthEndpoint = `${serverUrl}/healthz`;
|
||||
});
|
||||
|
||||
it('should return 200 for health', async () => {
|
||||
const response = await axios.get(HEALTH_ENDPOINT);
|
||||
const response = await axios.get(healthEndpoint);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.data).toBeDefined();
|
||||
});
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
export const SERVER_URL = process.env.TWENTY_API_URL ?? 'http://localhost:2020';
|
||||
import { ConfigService } from '@/cli/utilities/config/config-service';
|
||||
|
||||
export const getServerUrl = async (): Promise<string> => {
|
||||
const config = await new ConfigService().getConfig();
|
||||
|
||||
return config.apiUrl;
|
||||
};
|
||||
|
||||
@@ -5,20 +5,44 @@ import { beforeAll } from 'vitest';
|
||||
import { ensureDir } from '@/cli/utilities/file/fs-utils';
|
||||
import { getConfigPath } from '@/cli/utilities/config/get-config-path';
|
||||
|
||||
const testConfigPath = getConfigPath();
|
||||
const testConfigPath = getConfigPath(true);
|
||||
|
||||
beforeAll(async () => {
|
||||
const apiUrl = process.env.TWENTY_API_URL;
|
||||
const token = process.env.TWENTY_API_KEY;
|
||||
|
||||
if (!apiUrl || !token) {
|
||||
throw new Error(
|
||||
'TWENTY_API_URL and TWENTY_API_KEY must be set.\n' +
|
||||
'Run: twenty server start --test\n' +
|
||||
'Or set them in vitest env config.',
|
||||
);
|
||||
}
|
||||
|
||||
const response = await fetch(`${apiUrl}/healthz`).catch(() => null);
|
||||
|
||||
if (!response?.ok) {
|
||||
throw new Error(
|
||||
`Twenty server not reachable at ${apiUrl}. ` +
|
||||
'Run: twenty server start --test',
|
||||
);
|
||||
}
|
||||
|
||||
await ensureDir(path.dirname(testConfigPath));
|
||||
|
||||
const configFile = {
|
||||
remotes: {
|
||||
local: {
|
||||
apiUrl: process.env.TWENTY_API_URL,
|
||||
apiKey: process.env.TWENTY_API_KEY,
|
||||
await writeFile(
|
||||
testConfigPath,
|
||||
JSON.stringify(
|
||||
{
|
||||
remotes: {
|
||||
local: { apiUrl, apiKey: token },
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
},
|
||||
},
|
||||
defaultRemote: 'local',
|
||||
};
|
||||
null,
|
||||
2,
|
||||
),
|
||||
);
|
||||
|
||||
await writeFile(testConfigPath, JSON.stringify(configFile, null, 2));
|
||||
process.env.TWENTY_APP_ACCESS_TOKEN ??= token;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user