ce7cb702218693d08ea6d83464d2457c9250027c

This commit is contained in:
ms2k 2026-11-12 20:46:28 +09:00
commit 34c5f8963c
9 changed files with 145336 additions and 0 deletions

View file

@ -0,0 +1,26 @@
apiVersion: delivery.quorate.dev/v1alpha1
kind: ProjectDelivery
metadata:
name: mail-keys
namespace: project-delivery
spec:
source:
repository: https://forge.quorate.internal/quorate/cluster
continuous:
ref: refs/heads/master
paths:
- services/mail-keys
- services/project-delivery/actions/go-oci/cache.fsx
- services/project-delivery/actions/go-oci/contract.fsx
- services/project-delivery/actions/go-oci/image.fsx
- services/project-delivery/actions/go-oci/initialize.fsx
- services/project-delivery/actions/go-oci/kustomization.yaml
- services/project-delivery/actions/go-oci/publish.fsx
- services/project-delivery/actions/go-oci/source.fsx
- services/project-delivery/k8s/workflows/go-oci/base
- services/project-delivery/kustomization.yaml
targets:
- kind: QuayOCI
repository: quorate/mail-keys
workflowTemplateRef:
name: mail-keys-build

View file

@ -0,0 +1,64 @@
#load "projects.fsx"
#load "image.fsx"
open System
open System.IO
open Contract
open Image
open Projects
let revision = Environment.GetEnvironmentVariable "SOURCE_REVISION"
let project = Environment.GetEnvironmentVariable "TARGETS" |> decode<Target array> |> selectProject
let source = "/source/repository/services/mail-keys"
let working = directory "/output/working"
for path in Directory.EnumerateFiles(source, "*", SearchOption.AllDirectories) do
let target = Path.Combine(working, Path.GetRelativePath(source, path))
directory (Path.GetDirectoryName target) |> ignore
File.Copy(path, target)
let environment =
[ "HOME", "/tmp"; "PATH", "/toolchain/node/bin:/toolchain/usr/bin:/usr/bin:/bin"
"LD_LIBRARY_PATH", "/toolchain/usr/lib"; "npm_config_cache", "/tmp/npm" ]
requireSuccess
"/toolchain/usr/bin/busybox"
[ "cp"; "-a"; "/toolchain/frontend/node_modules"; Path.Combine(working, "node_modules") ]
None
environment
|> ignore
let checks =
Directory.EnumerateFiles(Path.Combine(working, "src"), "*.test.ts")
|> Seq.map (fun path -> Path.GetRelativePath(working, path))
|> Seq.toList
for arguments in
[ "--test" :: "--test-isolation=none" :: checks
[ "node_modules/typescript/bin/tsc"; "--noEmit" ]
[ "node_modules/vite/bin/vite.js"; "build" ] ] do
requireSuccess
"/toolchain/node/bin/node"
arguments
(Some working)
environment
|> ignore
let files _ =
let dist = Path.Combine(working, "dist")
(Directory.EnumerateFiles(dist, "*", SearchOption.AllDirectories)
|> Seq.map (fun path -> Path.Combine("usr/share/nginx/html/account", Path.GetRelativePath(dist, path)), path)
|> Seq.toList)
@ [ "etc/nginx/nginx.conf", "/orchestration/nginx.conf" ]
let digest =
assemble
"/toolchain/image-base"
"/output"
revision
[ "nginx"; "-g"; "daemon off;" ]
"/"
files
printfn "build=image project=%s digest=%s" project.Name digest

View file

@ -0,0 +1,53 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namePrefix: mail-keys-
resources:
- ../../../project-delivery/k8s/workflows/go-oci/base
- ../../../project-delivery/actions/go-oci
- network-policy.yaml
configMapGenerator:
- name: orch
namespace: project-delivery
behavior: merge
files:
- build.fsx
- go-oci.apko.yaml=runtime.apko.yaml
- projects.fsx
- toolchain.fsx
- nginx.conf
options:
labels:
app.kubernetes.io/instance: mail-keys
patches:
- target:
group: argoproj.io
version: v1alpha1
kind: WorkflowTemplate
name: build
patch: |-
- op: replace
path: /metadata/labels/app.kubernetes.io~1instance
value: mail-keys
- op: replace
path: /spec/podMetadata/labels/delivery.quorate.dev~1project
value: mail-keys
- op: remove
path: /spec/templates/2/dag/tasks/1/dependencies
- op: remove
path: /spec/templates/2/dag/tasks/2/dependencies
- op: replace
path: /spec/templates/2/dag/tasks/3/dependencies
value: [source-pull, cache-pull, toolchain-pull]
replacements:
- source:
kind: ConfigMap
name: mail-keys-orch
fieldPath: metadata.name
targets:
- select:
group: argoproj.io
version: v1alpha1
kind: WorkflowTemplate
name: mail-keys-build
fieldPaths:
- spec.templates.*.volumes.*.configMap.name

View file

@ -0,0 +1,31 @@
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: toolchain
namespace: project-delivery
spec:
endpointSelector:
matchLabels:
delivery.quorate.dev/stage: go-oci-toolchain
delivery.quorate.dev/project: mail-keys
egress:
- toEndpoints:
- matchLabels:
k8s:io.kubernetes.pod.namespace: kube-system
k8s-app: kube-dns
toPorts:
- ports:
- {port: "53", protocol: UDP}
- {port: "53", protocol: TCP}
rules:
dns:
- matchName: packages.wolfi.dev
- matchName: nodejs.org
- matchName: registry.npmjs.org
- toFQDNs:
- {matchName: packages.wolfi.dev}
- {matchName: nodejs.org}
- {matchName: registry.npmjs.org}
toPorts:
- ports:
- {port: "443", protocol: TCP}

View file

@ -0,0 +1,66 @@
pid /tmp/nginx.pid;
error_log /dev/stderr notice;
events {}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
access_log off;
client_body_temp_path /tmp/client_body;
proxy_temp_path /tmp/proxy;
fastcgi_temp_path /tmp/fastcgi;
uwsgi_temp_path /tmp/uwsgi;
scgi_temp_path /tmp/scgi;
map $server_port $client_addr {
default $remote_addr;
8082 $http_x_forwarded_for;
}
server {
listen 8082;
listen 8443 ssl;
server_name mail.quorate.dev;
absolute_redirect off;
client_max_body_size 80m;
root /usr/share/nginx/html;
ssl_certificate /run/tls/tls.crt;
ssl_certificate_key /run/tls/tls.key;
ssl_protocols TLSv1.2 TLSv1.3;
location = /healthz {
return 200 'ok';
}
location = / {
return 302 /account/;
}
location = /login {
return 302 /account/login;
}
location = /account/config.json {
alias /run/config/config.json;
default_type application/json;
add_header Cache-Control "no-store";
}
location /account/ {
try_files $uri $uri/ /account/index.html;
}
location / {
proxy_pass http://127.0.0.1:8081;
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $client_addr;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Connection "";
}
}
}

View file

@ -0,0 +1,36 @@
#load "contract.fsx"
open System.IO
open System.Runtime.InteropServices
open Contract
type Project =
{ Name: string
Workflow: string
Repository: string }
let project =
{ Name = "mail-keys"
Workflow = "mail-keys-build"
Repository = "quorate/mail-keys" }
let selectProject (targets: Target array) =
require
(targets.Length = 1
&& targets[0].Kind = "QuayOCI"
&& targets[0].Repository = project.Repository)
"invalid delivery target"
project
let inputPaths _ (_: Project) =
[ "services/mail-keys/package.json"; "services/mail-keys/package-lock.json" ]
let validateProject sourceRoot value =
inputPaths sourceRoot value
|> List.iter (fun path -> require (File.Exists(Path.Combine(sourceRoot, path))) $"missing input: {path}")
let toolchainProfileName = $"mail-keys-{RuntimeInformation.ProcessArchitecture}"
let toolchainCachePaths (_: Project) =
[ "node"; "frontend"; "usr"; "image-base" ]

View file

@ -0,0 +1,20 @@
contents:
keyring:
- https://packages.wolfi.dev/os/wolfi-signing.rsa.pub
repositories:
- https://packages.wolfi.dev/os
packages:
- nginx-stable=1.30.2-r0
- nginx-stable-mime-types=1.30.2-r0
- wolfi-baselayout=20230201-r30
accounts:
groups:
- groupname: application
gid: 65532
users:
- username: application
uid: 65532
gid: 65532
run-as: 65532
environment:
PATH: /usr/sbin:/usr/bin:/sbin:/bin

View file

@ -0,0 +1,120 @@
#load "projects.fsx"
open System
open System.IO
open System.Net.Http
open System.Runtime.InteropServices
open Contract
open Projects
let project =
Environment.GetEnvironmentVariable "TARGETS"
|> decode<Target array>
|> selectProject
let architecture, nodeArch, digest =
match RuntimeInformation.ProcessArchitecture with
| Architecture.X64 -> "x86_64", "x64", "5848553868b402d3fabb5b09270649977780a390f832155721025a08b5104455"
| Architecture.Arm64 -> "aarch64", "arm64", "439e9c438acdf6a6ffe47418da709153d66c4bed812e30a473faacb107dd2791"
| _ -> fail "unsupported build architecture"
if not (Handoff.primary "/state") then
printfn "toolchain=cache"
else
requireSuccess
"/sbin/apk"
[ "add"
"--root"
"/toolchain"
"--arch"
architecture
"--initdb"
"--no-scripts"
"--keys-dir"
"/etc/apk/keys"
"--repository"
"https://packages.wolfi.dev/os"
"busybox=1.38.0-r3"
"glibc-2.43=2.43-r18"
"ld-linux-2.43=2.43-r18"
"libgcc=16.2.0-r1"
"libstdc++=16.2.0-r1" ]
None
[]
|> ignore
let name = $"node-v26.13.0-linux-{nodeArch}"
let archive = "/tmp/node.tar.gz"
use client = new HttpClient(Timeout = TimeSpan.FromMinutes 5.0)
use input =
client
.GetStreamAsync($"https://nodejs.org/dist/v26.13.0/{name}.tar.gz", cancellationToken)
.GetAwaiter()
.GetResult()
do
use output = File.Create archive
input.CopyTo output
require (sha256 archive = digest) "Node.js checksum mismatch"
extractGzip archive "/toolchain"
Directory.Move($"/toolchain/{name}", "/toolchain/node")
File.Delete archive
use npm =
client
.GetStreamAsync("https://registry.npmjs.org/npm/-/npm-12.2.1.tgz", cancellationToken)
.GetAwaiter()
.GetResult()
do
use output = File.Create archive
npm.CopyTo output
require
(sha256 archive = "228bd64aaef23270dbdbd2cf3d5ef5c467602ef38c4066246cef1984adab9a67")
"npm checksum mismatch"
extractGzip archive (directory "/toolchain/npm")
Directory.Delete("/toolchain/node/lib/node_modules/npm", true)
Directory.Move("/toolchain/npm/package", "/toolchain/node/lib/node_modules/npm")
File.Delete archive
directory "/toolchain/frontend" |> ignore
[ "package.json"; "package-lock.json" ]
|> List.iter (fun name -> File.Copy($"/source/repository/services/mail-keys/{name}", $"/toolchain/frontend/{name}"))
let environment =
[ "HOME", "/tmp"
"PATH", "/toolchain/node/bin:/usr/bin:/bin"
"LD_LIBRARY_PATH", "/toolchain/usr/lib"
"npm_config_cache", "/tmp/npm" ]
requireSuccess
"/toolchain/node/bin/node"
[ "/toolchain/node/lib/node_modules/npm/bin/npm-cli.js"
"ci"
"--ignore-scripts"
"--no-audit"
"--no-fund" ]
(Some "/toolchain/frontend")
environment
|> ignore
directory "/toolchain/image-base" |> ignore
requireSuccess
"/usr/bin/apko"
[ "build"
"--arch"
"x86_64,arm64"
"--sbom=false"
"/orchestration/go-oci.apko.yaml"
"mail-keys:base"
"/toolchain/image-base" ]
None
environment
|> ignore
printfn "toolchain=primary project=%s" project.Name

View file

@ -0,0 +1,5 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- delivery.yaml
- delivery