add workflows: build-push-ghcr-images
This commit is contained in:
parent
c894924a57
commit
484734352d
69
.github/workflows/build-push-ghcr-image.yml
vendored
Normal file
69
.github/workflows/build-push-ghcr-image.yml
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
name: Build And Push GHCR Image
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
image_tag:
|
||||
description: Optional image tag. Defaults to the current commit SHA.
|
||||
required: false
|
||||
type: string
|
||||
push_latest:
|
||||
description: Also publish the `latest` tag.
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
image_tag:
|
||||
description: Optional image tag. Defaults to the current commit SHA.
|
||||
required: false
|
||||
type: string
|
||||
push_latest:
|
||||
description: Also publish the `latest` tag.
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
concurrency:
|
||||
group: build-push-ghcr-image-console-${{ github.ref_name }}
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
PRIMARY_DOMAIN: console.svc.plus
|
||||
NEXT_PUBLIC_RUNTIME_ENVIRONMENT: prod
|
||||
NEXT_PUBLIC_RUNTIME_REGION: cn
|
||||
steps:
|
||||
- name: Check Out Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log In To GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ vars.GHCR_USERNAME || github.repository_owner }}
|
||||
password: ${{ secrets.GHCR_TOKEN || github.token }}
|
||||
|
||||
- name: Compute Image Metadata
|
||||
id: metadata
|
||||
env:
|
||||
IMAGE_TAG_INPUT: ${{ inputs.image_tag }}
|
||||
run: |
|
||||
bash scripts/github-actions/compute-frontend-release-metadata.sh "${IMAGE_TAG_INPUT}"
|
||||
|
||||
- name: Publish Frontend Image
|
||||
env:
|
||||
IMAGE_REF: ${{ steps.metadata.outputs.image_ref }}
|
||||
IMAGE_LATEST_REF: ${{ steps.metadata.outputs.image_latest_ref }}
|
||||
PUSH_LATEST: ${{ inputs.push_latest }}
|
||||
run: |
|
||||
bash scripts/github-actions/build-and-push-frontend-image.sh
|
||||
@ -90,6 +90,7 @@ export type IntegrationDefaults = {
|
||||
vaultSecretKey: string
|
||||
apisixUrl: string
|
||||
apisixTokenConfigured: boolean
|
||||
externalServices?: string[]
|
||||
}
|
||||
|
||||
export function normalizeMainSessionKey(value?: string | null): string {
|
||||
|
||||
49
src/server/consoleIntegrations.test.ts
Normal file
49
src/server/consoleIntegrations.test.ts
Normal file
@ -0,0 +1,49 @@
|
||||
// @vitest-environment node
|
||||
|
||||
import { afterAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
const ORIGINAL_ENV = { ...process.env };
|
||||
|
||||
describe("consoleIntegrations", () => {
|
||||
beforeEach(() => {
|
||||
process.env = { ...ORIGINAL_ENV };
|
||||
delete process.env.EXTERNAL_SERVICES;
|
||||
delete process.env.NEXT_PUBLIC_EXTERNAL_SERVICES;
|
||||
delete process.env.EXTERNAL_SERVICE;
|
||||
delete process.env.NEXT_PUBLIC_EXTERNAL_SERVICE;
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
process.env = ORIGINAL_ENV;
|
||||
});
|
||||
|
||||
it("parses configured external services into a stable list", async () => {
|
||||
process.env.EXTERNAL_SERVICES =
|
||||
"docs.svc.plus, xworkmate.svc.plus\nopenclaw-gateway.svc.plus";
|
||||
|
||||
const { getConsoleIntegrationDefaults } = await import("./consoleIntegrations");
|
||||
|
||||
expect(getConsoleIntegrationDefaults().externalServices).toEqual([
|
||||
"docs.svc.plus",
|
||||
"xworkmate.svc.plus",
|
||||
"openclaw-gateway.svc.plus",
|
||||
]);
|
||||
});
|
||||
|
||||
it("defaults to an empty external services list when unset", async () => {
|
||||
const { getConsoleIntegrationDefaults } = await import("./consoleIntegrations");
|
||||
|
||||
expect(getConsoleIntegrationDefaults().externalServices).toEqual([]);
|
||||
});
|
||||
|
||||
it("accepts the singular external service env var as a fallback", async () => {
|
||||
process.env.EXTERNAL_SERVICE = "docs.svc.plus;xworkmate.svc.plus";
|
||||
|
||||
const { getConsoleIntegrationDefaults } = await import("./consoleIntegrations");
|
||||
|
||||
expect(getConsoleIntegrationDefaults().externalServices).toEqual([
|
||||
"docs.svc.plus",
|
||||
"xworkmate.svc.plus",
|
||||
]);
|
||||
});
|
||||
});
|
||||
@ -23,6 +23,12 @@ const APISIX_TOKEN_KEYS = ['AI_GATEWAY_ACCESS_TOKEN', 'AI_GATEWAY_API_KEY'] as c
|
||||
const VAULT_URL_KEYS = ['VAULT_SERVER_URL', 'VAULT_ADDR', 'vault_addr'] as const
|
||||
const VAULT_NAMESPACE_KEYS = ['VAULT_NAMESPACE'] as const
|
||||
const VAULT_TOKEN_KEYS = ['VAULT_TOKEN', 'VAULT_SERVER_ROOT_ACCESS_TOKEN'] as const
|
||||
const EXTERNAL_SERVICES_KEYS = [
|
||||
'EXTERNAL_SERVICES',
|
||||
'NEXT_PUBLIC_EXTERNAL_SERVICES',
|
||||
'EXTERNAL_SERVICE',
|
||||
'NEXT_PUBLIC_EXTERNAL_SERVICE',
|
||||
] as const
|
||||
|
||||
function readEnvValue(...keys: readonly string[]): string | undefined {
|
||||
for (const key of keys) {
|
||||
@ -59,6 +65,18 @@ function normalizeHttpUrl(value?: string): string {
|
||||
}
|
||||
}
|
||||
|
||||
function parseServiceList(value?: string): string[] {
|
||||
const raw = value?.trim() ?? ''
|
||||
if (!raw) {
|
||||
return []
|
||||
}
|
||||
|
||||
return raw
|
||||
.split(/[\n,;]+/)
|
||||
.map((item) => item.trim())
|
||||
.filter((item) => item.length > 0)
|
||||
}
|
||||
|
||||
function normalizeWsUrl(value?: string): string {
|
||||
const raw = value?.trim() ?? ''
|
||||
if (raw.length === 0) {
|
||||
@ -92,6 +110,7 @@ export function getConsoleIntegrationDefaults(): IntegrationDefaults {
|
||||
vaultSecretKey: '',
|
||||
apisixUrl: normalizeHttpUrl(readEnvValue(...APISIX_URL_KEYS)),
|
||||
apisixTokenConfigured: Boolean(readEnvValue(...APISIX_TOKEN_KEYS)),
|
||||
externalServices: parseServiceList(readEnvValue(...EXTERNAL_SERVICES_KEYS)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user