Compare commits
No commits in common. "main" and "feat/platform-values" have entirely different histories.
main
...
feat/platf
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
dist/
|
|
||||||
node_modules/
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
# Fixture Review Contract
|
|
||||||
|
|
||||||
- Canonical E2E source lives in `Maidn/maidn-e2e-secret`; `origin` must target that repository.
|
|
||||||
- `test-org-2` is disposable-only and must never be treated as the test-suite source or delivery owner.
|
|
||||||
- Keep fixture changes on one scoped branch and open a Forgejo pull request for review.
|
|
||||||
- Before review, run `git diff --check` and the applicable build or test command.
|
|
||||||
- Return review requests as: PR URL, branch, purpose, checks, risk, and merge action.
|
|
||||||
- Do not commit credentials, token files, generated workspaces, or Kubernetes Secret values.
|
|
||||||
17
Dockerfile
17
Dockerfile
|
|
@ -1,17 +0,0 @@
|
||||||
FROM node:22-alpine AS build
|
|
||||||
WORKDIR /app
|
|
||||||
COPY package.json .
|
|
||||||
RUN npm install --package-lock=false
|
|
||||||
COPY tsconfig.json .
|
|
||||||
COPY src ./src
|
|
||||||
RUN npm run build
|
|
||||||
|
|
||||||
FROM node:22-alpine
|
|
||||||
WORKDIR /app
|
|
||||||
ENV NODE_ENV=production PORT=8080
|
|
||||||
COPY package.json .
|
|
||||||
RUN npm install --omit=dev --package-lock=false && npm cache clean --force
|
|
||||||
COPY --from=build /app/dist ./dist
|
|
||||||
USER node
|
|
||||||
EXPOSE 8080
|
|
||||||
CMD ["npm", "start"]
|
|
||||||
4
charts/maidn-e2e-secret/Chart.yaml
Normal file
4
charts/maidn-e2e-secret/Chart.yaml
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
apiVersion: v2
|
||||||
|
name: maidn-e2e-secret
|
||||||
|
description: Maidn E2E secret runtime fixture
|
||||||
|
version: 0.1.0
|
||||||
48
charts/maidn-e2e-secret/templates/deployment.yaml
Normal file
48
charts/maidn-e2e-secret/templates/deployment.yaml
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ .Chart.Name }}
|
||||||
|
labels:
|
||||||
|
app: {{ .Chart.Name }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: {{ .Chart.Name }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: {{ .Chart.Name }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- range . }}
|
||||||
|
- name: {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: 8080
|
||||||
|
{{- if or (eq .Release.Namespace "staging") (eq .Release.Namespace "production") }}
|
||||||
|
env:
|
||||||
|
- name: E2E_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ printf "%s-runtime-%s" .Chart.Name .Release.Namespace }}
|
||||||
|
key: {{ .Values.runtimeSecret.key | quote }}
|
||||||
|
- name: DATABASE_URL
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: {{ printf "%s-postgres-app" .Release.Namespace }}
|
||||||
|
key: uri
|
||||||
|
- name: MAIDN_RUNTIME_REQUIRED
|
||||||
|
value: "true"
|
||||||
|
{{- end }}
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: http
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: external-secrets.io/v1
|
||||||
|
kind: ExternalSecret
|
||||||
|
metadata:
|
||||||
|
name: forgejo-registry-credentials
|
||||||
|
spec:
|
||||||
|
secretStoreRef:
|
||||||
|
kind: ClusterSecretStore
|
||||||
|
name: openbao
|
||||||
|
target:
|
||||||
|
name: forgejo-registry-credentials
|
||||||
|
creationPolicy: Owner
|
||||||
|
template:
|
||||||
|
type: kubernetes.io/dockerconfigjson
|
||||||
|
data:
|
||||||
|
.dockerconfigjson: "{{ `{{ .dockerconfigjson }}` }}"
|
||||||
|
data:
|
||||||
|
- secretKey: dockerconfigjson
|
||||||
|
remoteRef:
|
||||||
|
key: cicd/forgejo-registry
|
||||||
|
property: dockerconfigjson
|
||||||
17
charts/maidn-e2e-secret/templates/httproute.yaml
Normal file
17
charts/maidn-e2e-secret/templates/httproute.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
apiVersion: gateway.networking.k8s.io/v1
|
||||||
|
kind: HTTPRoute
|
||||||
|
metadata:
|
||||||
|
name: {{ .Chart.Name }}
|
||||||
|
spec:
|
||||||
|
parentRefs:
|
||||||
|
- name: {{ .Values.gateway.name }}
|
||||||
|
namespace: {{ .Values.gateway.namespace }}
|
||||||
|
sectionName: http
|
||||||
|
{{- with .Values.gateway.hostname }}
|
||||||
|
hostnames:
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
- backendRefs:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
port: 8080
|
||||||
12
charts/maidn-e2e-secret/templates/service.yaml
Normal file
12
charts/maidn-e2e-secret/templates/service.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ .Chart.Name }}
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
selector:
|
||||||
|
app: {{ .Chart.Name }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
port: 8080
|
||||||
|
targetPort: http
|
||||||
16
charts/maidn-e2e-secret/values.yaml
Normal file
16
charts/maidn-e2e-secret/values.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: ""
|
||||||
|
tag: dev
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
imagePullSecrets:
|
||||||
|
- forgejo-registry-credentials
|
||||||
|
|
||||||
|
runtimeSecret:
|
||||||
|
key: e2e-secret
|
||||||
|
|
||||||
|
gateway:
|
||||||
|
name: public
|
||||||
|
namespace: gateway-system
|
||||||
|
hostname: ""
|
||||||
19
package.json
19
package.json
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"name": "maidn-e2e-secret",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
|
||||||
"build": "tsc",
|
|
||||||
"start": "node dist/index.js",
|
|
||||||
"test": "npm run build && node --test test/health.test.js"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"express": "^5.1.0",
|
|
||||||
"pg": "^8.16.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/express": "^5.0.1",
|
|
||||||
"@types/node": "^22.15.0",
|
|
||||||
"@types/pg": "^8.15.5",
|
|
||||||
"typescript": "~5.8.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
preview/values.yaml
Normal file
1
preview/values.yaml
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
replicaCount: 1
|
||||||
2
production/values.yaml
Normal file
2
production/values.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
gateway:
|
||||||
|
hostname: maidn-e2e-secret.dev02.nid3.com
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import { Client } from 'pg';
|
|
||||||
|
|
||||||
export async function isReady(selectOne = databaseSelectOne) {
|
|
||||||
if (process.env.MAIDN_RUNTIME_REQUIRED !== 'true') return true;
|
|
||||||
if (!process.env.E2E_SECRET || !process.env.DATABASE_URL) return false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await selectOne();
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function databaseSelectOne() {
|
|
||||||
const client = new Client({ connectionString: process.env.DATABASE_URL });
|
|
||||||
await client.connect();
|
|
||||||
try {
|
|
||||||
await client.query('SELECT 1');
|
|
||||||
} finally {
|
|
||||||
await client.end();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
11
src/index.ts
11
src/index.ts
|
|
@ -1,11 +0,0 @@
|
||||||
import express from 'express';
|
|
||||||
import { isReady } from './health.js';
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.get('/', async (_request, response) => {
|
|
||||||
const ready = await isReady();
|
|
||||||
response.status(ready ? 200 : 503).send(ready ? 'maidn-e2e-secret-ready' : 'maidn-e2e-secret-not-ready');
|
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(process.env.PORT ?? 8080);
|
|
||||||
2
staging/values.yaml
Normal file
2
staging/values.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
gateway:
|
||||||
|
hostname: maidn-e2e-secret-staging.dev02.nid3.com
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
const assert = require('node:assert/strict');
|
|
||||||
const test = require('node:test');
|
|
||||||
const { isReady } = require('../dist/health.js');
|
|
||||||
|
|
||||||
test('readiness requires the secret and a successful database query', async () => {
|
|
||||||
const secret = process.env.E2E_SECRET;
|
|
||||||
const databaseUrl = process.env.DATABASE_URL;
|
|
||||||
const runtimeRequired = process.env.MAIDN_RUNTIME_REQUIRED;
|
|
||||||
|
|
||||||
try {
|
|
||||||
delete process.env.MAIDN_RUNTIME_REQUIRED;
|
|
||||||
assert.equal(await isReady(async () => assert.fail('query should not run')), true);
|
|
||||||
|
|
||||||
process.env.MAIDN_RUNTIME_REQUIRED = 'true';
|
|
||||||
delete process.env.E2E_SECRET;
|
|
||||||
assert.equal(await isReady(async () => assert.fail('query should not run')), false);
|
|
||||||
|
|
||||||
process.env.E2E_SECRET = 'configured';
|
|
||||||
delete process.env.DATABASE_URL;
|
|
||||||
assert.equal(await isReady(async () => assert.fail('query should not run')), false);
|
|
||||||
|
|
||||||
process.env.DATABASE_URL = 'postgres://example';
|
|
||||||
assert.equal(await isReady(async () => {}), true);
|
|
||||||
assert.equal(await isReady(async () => { throw new Error('unavailable'); }), false);
|
|
||||||
} finally {
|
|
||||||
if (secret === undefined) delete process.env.E2E_SECRET;
|
|
||||||
else process.env.E2E_SECRET = secret;
|
|
||||||
if (databaseUrl === undefined) delete process.env.DATABASE_URL;
|
|
||||||
else process.env.DATABASE_URL = databaseUrl;
|
|
||||||
if (runtimeRequired === undefined) delete process.env.MAIDN_RUNTIME_REQUIRED;
|
|
||||||
else process.env.MAIDN_RUNTIME_REQUIRED = runtimeRequired;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "NodeNext",
|
|
||||||
"moduleResolution": "NodeNext",
|
|
||||||
"outDir": "dist",
|
|
||||||
"strict": true,
|
|
||||||
"target": "ES2022"
|
|
||||||
},
|
|
||||||
"include": ["src"]
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue