fix(server): auto import config.json (#11255)
This commit is contained in:
19
.github/actions/copilot-test/action.yml
vendored
19
.github/actions/copilot-test/action.yml
vendored
@@ -5,35 +5,16 @@ inputs:
|
|||||||
description: 'Script to run'
|
description: 'Script to run'
|
||||||
default: 'yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only'
|
default: 'yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only'
|
||||||
required: false
|
required: false
|
||||||
openai-key:
|
|
||||||
description: 'OpenAI secret key'
|
|
||||||
required: true
|
|
||||||
google-key:
|
|
||||||
description: 'Google secret key'
|
|
||||||
required: true
|
|
||||||
fal-key:
|
|
||||||
description: 'Fal secret key'
|
|
||||||
required: true
|
|
||||||
perplexity-key:
|
|
||||||
description: 'Perplexity secret key'
|
|
||||||
required: true
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'composite'
|
using: 'composite'
|
||||||
steps:
|
steps:
|
||||||
- name: Prepare Server Test Environment
|
|
||||||
uses: ./.github/actions/server-test-env
|
|
||||||
|
|
||||||
- name: Server Copilot E2E Test
|
- name: Server Copilot E2E Test
|
||||||
shell: bash
|
shell: bash
|
||||||
run: ${{ inputs.script }}
|
run: ${{ inputs.script }}
|
||||||
env:
|
env:
|
||||||
COPILOT: true
|
COPILOT: true
|
||||||
DEV_SERVER_URL: http://localhost:8080
|
DEV_SERVER_URL: http://localhost:8080
|
||||||
COPILOT_OPENAI_API_KEY: ${{ inputs.openai-key }}
|
|
||||||
COPILOT_GOOGLE_API_KEY: ${{ inputs.google-key }}
|
|
||||||
COPILOT_FAL_API_KEY: ${{ inputs.fal-key }}
|
|
||||||
COPILOT_PERPLEXITY_API_KEY: ${{ inputs.perplexity-key }}
|
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
|
|||||||
8
.github/actions/server-test-env/action.yml
vendored
8
.github/actions/server-test-env/action.yml
vendored
@@ -21,3 +21,11 @@ runs:
|
|||||||
yarn affine @affine/server prisma generate
|
yarn affine @affine/server prisma generate
|
||||||
yarn affine @affine/server prisma migrate deploy
|
yarn affine @affine/server prisma migrate deploy
|
||||||
yarn affine @affine/server data-migration run
|
yarn affine @affine/server data-migration run
|
||||||
|
- name: Import config
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
printf '{"copilot":{"enabled":true,"providers.fal":{"apiKey":"%s"},"providers.gemini":{"apiKey":"%s"},"providers.openai":{"apiKey":"%s"},"providers.perplexity":{"apiKey":"%s"}}}' \
|
||||||
|
"$COPILOT_FAL_API_KEY" \
|
||||||
|
"$COPILOT_GOOGLE_API_KEY" \
|
||||||
|
"$COPILOT_OPENAI_API_KEY" \
|
||||||
|
"$COPILOT_PERPLEXITY_API_KEY" > ./packages/backend/server/config.json
|
||||||
|
|||||||
29
.github/workflows/build-test.yml
vendored
29
.github/workflows/build-test.yml
vendored
@@ -555,8 +555,6 @@ jobs:
|
|||||||
run: yarn affine @affine/server test:coverage --forbid-only
|
run: yarn affine @affine/server test:coverage --forbid-only
|
||||||
env:
|
env:
|
||||||
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
||||||
COPILOT_OPENAI_API_KEY: 'use_fake_openai_api_key'
|
|
||||||
COPILOT_GOOGLE_API_KEY: 'use_fake_google_api_key'
|
|
||||||
CI_NODE_INDEX: ${{ matrix.node_index }}
|
CI_NODE_INDEX: ${{ matrix.node_index }}
|
||||||
CI_NODE_TOTAL: ${{ matrix.total_nodes }}
|
CI_NODE_TOTAL: ${{ matrix.total_nodes }}
|
||||||
|
|
||||||
@@ -617,8 +615,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Run server tests
|
- name: Run server tests
|
||||||
run: yarn affine @affine/server e2e:coverage --forbid-only
|
run: yarn affine @affine/server e2e:coverage --forbid-only
|
||||||
env:
|
|
||||||
COPILOT_OPENAI_API_KEY: 'use_fake_openai_api_key'
|
|
||||||
|
|
||||||
- name: Upload server test coverage results
|
- name: Upload server test coverage results
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
@@ -721,6 +717,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Prepare Server Test Environment
|
- name: Prepare Server Test Environment
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
||||||
|
env:
|
||||||
|
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
||||||
|
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
||||||
|
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
||||||
|
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
||||||
uses: ./.github/actions/server-test-env
|
uses: ./.github/actions/server-test-env
|
||||||
|
|
||||||
- name: Run server tests
|
- name: Run server tests
|
||||||
@@ -728,10 +729,6 @@ jobs:
|
|||||||
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
||||||
env:
|
env:
|
||||||
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
||||||
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
|
||||||
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
|
||||||
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
|
||||||
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
|
||||||
|
|
||||||
- name: Upload server test coverage results
|
- name: Upload server test coverage results
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
||||||
@@ -813,15 +810,20 @@ jobs:
|
|||||||
name: server-native.node
|
name: server-native.node
|
||||||
path: ./packages/backend/server
|
path: ./packages/backend/server
|
||||||
|
|
||||||
|
- name: Prepare Server Test Environment
|
||||||
|
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
||||||
|
env:
|
||||||
|
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
||||||
|
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
||||||
|
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
||||||
|
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
||||||
|
uses: ./.github/actions/server-test-env
|
||||||
|
|
||||||
- name: Run Copilot E2E Test ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
- name: Run Copilot E2E Test ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
||||||
uses: ./.github/actions/copilot-test
|
uses: ./.github/actions/copilot-test
|
||||||
with:
|
with:
|
||||||
script: yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
script: yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
||||||
openai-key: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
|
||||||
google-key: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
|
||||||
fal-key: ${{ secrets.COPILOT_FAL_API_KEY }}
|
|
||||||
perplexity-key: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
|
||||||
|
|
||||||
cloud-e2e-test:
|
cloud-e2e-test:
|
||||||
name: ${{ matrix.tests.name }}
|
name: ${{ matrix.tests.name }}
|
||||||
@@ -917,9 +919,6 @@ jobs:
|
|||||||
${{ matrix.tests.script }}
|
${{ matrix.tests.script }}
|
||||||
env:
|
env:
|
||||||
DEV_SERVER_URL: http://localhost:8080
|
DEV_SERVER_URL: http://localhost:8080
|
||||||
COPILOT_OPENAI_API_KEY: 1
|
|
||||||
COPILOT_FAL_API_KEY: 1
|
|
||||||
COPILOT_PERPLEXITY_API_KEY: 1
|
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
if: always()
|
if: always()
|
||||||
|
|||||||
9
.github/workflows/copilot-test.yml
vendored
9
.github/workflows/copilot-test.yml
vendored
@@ -76,16 +76,17 @@ jobs:
|
|||||||
path: ./packages/backend/server
|
path: ./packages/backend/server
|
||||||
|
|
||||||
- name: Prepare Server Test Environment
|
- name: Prepare Server Test Environment
|
||||||
|
env:
|
||||||
|
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
||||||
|
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
||||||
|
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
||||||
|
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
||||||
uses: ./.github/actions/server-test-env
|
uses: ./.github/actions/server-test-env
|
||||||
|
|
||||||
- name: Run server tests
|
- name: Run server tests
|
||||||
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
||||||
env:
|
env:
|
||||||
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
||||||
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
|
||||||
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
|
||||||
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
|
|
||||||
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
|
|
||||||
|
|
||||||
- name: Upload server test coverage results
|
- name: Upload server test coverage results
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
|
|||||||
1
packages/backend/server/.gitignore
vendored
1
packages/backend/server/.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
|
config.json
|
||||||
.env
|
.env
|
||||||
static/
|
static/
|
||||||
|
|||||||
3
packages/backend/server/config.example.json
Normal file
3
packages/backend/server/config.example.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../../../.docker/selfhost/schema.json"
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import { once, set } from 'lodash-es';
|
import { existsSync, readFileSync } from 'node:fs';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
import { merge, once, set } from 'lodash-es';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { type EnvConfigType, parseEnvValue } from './env';
|
import { type EnvConfigType, parseEnvValue } from './env';
|
||||||
@@ -205,6 +208,34 @@ export function defineModuleConfig<T extends keyof AppConfigSchema>(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function readConfigJSONOverrides() {
|
||||||
|
if (existsSync(join(env.projectRoot, 'config.json'))) {
|
||||||
|
try {
|
||||||
|
const config = JSON.parse(
|
||||||
|
readFileSync(join(env.projectRoot, 'config.json'), 'utf-8')
|
||||||
|
) as AppConfig;
|
||||||
|
|
||||||
|
const overrides = {};
|
||||||
|
|
||||||
|
Object.entries(config).forEach(([key, value]) => {
|
||||||
|
if (key === '$schema') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.entries(value).forEach(([k, v]) => {
|
||||||
|
set(overrides, `${key}.${k}`, v);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return overrides;
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Invalid json config file', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
export function getDefaultConfig(): AppConfigSchema {
|
export function getDefaultConfig(): AppConfigSchema {
|
||||||
const config: Record<string, any> = {};
|
const config: Record<string, any> = {};
|
||||||
const envs = process.env;
|
const envs = process.env;
|
||||||
@@ -235,5 +266,9 @@ export function getDefaultConfig(): AppConfigSchema {
|
|||||||
config[module] = modulizedConfig;
|
config[module] = modulizedConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fileOverrides = readConfigJSONOverrides();
|
||||||
|
|
||||||
|
merge(config, fileOverrides);
|
||||||
|
|
||||||
return config as AppConfigSchema;
|
return config as AppConfigSchema;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ export class ServerService implements OnApplicationBootstrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent('config.changed.broadcast')
|
@OnEvent('config.changed.broadcast')
|
||||||
onConfigChangedBroadcast(updates: DeepPartial<AppConfig>) {
|
onConfigChangedBroadcast(event: Events['config.changed.broadcast']) {
|
||||||
this.configFactory.override(updates);
|
this.configFactory.override(event.updates);
|
||||||
this.event.emit('config.changed', { updates });
|
this.event.emit('config.changed', event);
|
||||||
}
|
}
|
||||||
|
|
||||||
async revalidateConfig() {
|
async revalidateConfig() {
|
||||||
|
|||||||
Reference in New Issue
Block a user