Author SHA1 Message Date
argoyleandClaude Opus 5.5 0f7610d03f fix: make the nginx config readable by the unprivileged user
schemas-app / build (pull_request) Successful in 4m9s
schemas-app / deploy-prod-frostmoln (pull_request) Skipped
COPY keeps the source file's mode; a 600 file (local checkouts) left
uid 101 unable to read it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ma8eHhW59hLAJuLzBnLvUu
2026-10-14 22:26:30 +02:00
argoyleandClaude Opus 5.5 1646ee1bc3 feat: deploy to Frostmoln production
The AWS deploy-prod job has failed since CI left AWS (no k8s.unbound.se
context on the runners). Deploys now go to the Frostmoln production
cluster (namespace schemas), the way the sites do.

Frostmoln enforces restricted Pod Security: the pod runs as the image's
non-root user with a matching securityContext. The prod-only manifests
move to the prod-frostmoln target; the ALB ingress becomes a Traefik one
with a Let's Encrypt certificate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ma8eHhW59hLAJuLzBnLvUu
2026-10-14 22:15:38 +02:00
renovate acf6f8df62 chore(deps): update nginx docker tag to v1.31.7 (#390)
schemas-app / build (push) Successful in 22s
schemas-app / deploy-prod (push) Failing after 10s
2026-10-14 19:41:31 +00:00
renovate f85171ce54 chore(deps): update dependency @vitejs/plugin-vue to v6.0.10 (#389)
schemas-app / build (push) Failing after 4s
schemas-app / deploy-prod (push) Skipped
2026-10-13 09:32:11 +00:00
renovate f67e1bf784 fix(deps): update dependency nuxt to v4.6.1 (#388)
schemas-app / build (push) Successful in 7m39s
schemas-app / deploy-prod (push) Failing after 10s
2026-10-13 06:04:32 +00:00
renovate 06193f2d96 chore(deps): update graphqlcodegenerator monorepo (#387)
schemas-app / build (push) Successful in 24m21s
schemas-app / deploy-prod (push) Failing after 8s
2026-10-13 05:37:16 +00:00
renovate 88f675760c chore(deps): update dependency @graphql-codegen/cli to v7.4.5 (#386)
schemas-app / build (push) Successful in 15m22s
schemas-app / deploy-prod (push) Failing after 2m22s
2026-10-10 15:22:40 +00:00
renovate fbb0d555eb fix(deps): update dependency nuxt to v4.6.0 (#385)
schemas-app / deploy-prod (push) Failing after 18s
schemas-app / build (push) Successful in 50s
2026-10-08 23:25:05 +00:00
renovate df6943512f chore(deps): update dependency typescript-eslint to v8.71.1 (#384)
schemas-app / build (push) Successful in 1m2s
schemas-app / deploy-prod (push) Failing after 20s
2026-10-08 18:22:39 +00:00
renovate 30190b678d chore(deps): update graphqlcodegenerator monorepo (#383)
schemas-app / build (push) Successful in 1m30s
schemas-app / deploy-prod (push) Failing after 17s
2026-10-08 16:23:31 +00:00
renovate 8281ede8e0 chore(deps): update dependency jsdom to v30.1.2 (#382)
schemas-app / build (push) Successful in 46s
schemas-app / deploy-prod (push) Failing after 18s
2026-10-07 10:23:34 +00:00
renovate 5489b2a617 chore(deps): update pre-commit hook pre-commit/mirrors-eslint to v10.12.0 (#381)
schemas-app / build (push) Successful in 36s
schemas-app / deploy-prod (push) Successful in 1m9s
2026-10-06 15:21:58 +00:00
renovate 471deee94e chore(deps): update nginx:1.31.6 docker digest to 9a54e7e (#380)
schemas-app / build (push) Successful in 38s
schemas-app / deploy-prod (push) Failing after 55s
2026-10-06 04:38:33 +00:00
renovate f095c6c979 chore(deps): update dependency eslint to v10.12.0 (#379)
schemas-app / build (push) Successful in 40s
schemas-app / deploy-prod (push) Successful in 1m6s
2026-10-05 22:18:47 +00:00
renovate 640fc9ef3b chore(deps): update dependency stylelint to v17.16.0 (#378)
schemas-app / build (push) Successful in 56s
schemas-app / deploy-prod (push) Successful in 1m9s
2026-10-04 11:12:56 +00:00
renovate 3851de6879 chore(deps): update vitest monorepo to v5.0.3 (#377)
schemas-app / build (push) Successful in 39s
schemas-app / deploy-prod (push) Successful in 1m9s
2026-10-03 12:13:33 +00:00
argoyle b477fed57d chore(k8s): take the image reference from build-tools (#376)
schemas-app / build (push) Successful in 47s
schemas-app / deploy-prod (push) Successful in 1m15s
## Summary

`k8s/deploy.yaml` takes the image from build-tools: `image: ${IMAGE}` instead of the hard-coded `oci.unbound.se/unboundsoftware/schemas-app:${COMMIT}`.

`deploy` substitutes `${IMAGE}` with `<registry>/<owner>/<name>:<tag>`, where the registry comes from the build-tools config and the tag is the value `${COMMIT}` gets today. The rendered reference is unchanged. Moving off `oci.unbound.se` later becomes one change in infra.

Validated on shiny/time-service#864: merged and deployed to AWS staging and Frostmoln staging with the same image. Prerequisites, all merged:
- unboundsoftware/infra#1808: registry in `BUILDTOOLS_FROSTMOLN_STAGING`
- shiny/acctest#952: acctest pins build-tools to the Gitea registry

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://gitea.unbound.se/unboundsoftware/schemas-app/pulls/376
2026-10-02 22:40:09 +00:00
renovate 519554ae0e chore(deps): update dependency @graphql-codegen/typescript-operations to v6.1.9 (#375)
schemas-app / build (push) Successful in 38s
schemas-app / deploy-prod (push) Successful in 1m7s
2026-10-02 15:15:47 +00:00
renovate 842403b109 chore(deps): update dependency typescript-eslint to v8.71.0 (#374)
schemas-app / build (push) Successful in 56s
schemas-app / deploy-prod (push) Successful in 1m24s
2026-10-01 19:17:54 +00:00
renovate eb13f78944 fix(deps): update dependency @auth0/auth0-vue to v2.11.0 (#373)
schemas-app / build (push) Successful in 1m52s
schemas-app / deploy-prod (push) Successful in 1m33s
2026-10-01 14:15:11 +00:00
renovate 6d9911ce4b chore(deps): update graphqlcodegenerator monorepo (#372)
schemas-app / build (push) Successful in 2m27s
schemas-app / deploy-prod (push) Successful in 1m18s
2026-10-01 14:15:02 +00:00
renovate 00fed95fd7 chore(deps): update vitest monorepo to v5.0.2 (#371)
schemas-app / build (push) Successful in 34s
schemas-app / deploy-prod (push) Successful in 1m17s
2026-09-28 10:17:33 +00:00
renovate aea131d565 fix(deps): update dependency graphql-ws to v6.3.0 (#370)
schemas-app / build (push) Successful in 37s
schemas-app / deploy-prod (push) Successful in 1m17s
2026-09-27 19:16:52 +00:00
renovate 0b8eabc073 chore(deps): update dependency @graphql-codegen/cli to v7.4.3 (#369)
schemas-app / build (push) Successful in 37s
schemas-app / deploy-prod (push) Successful in 1m15s
2026-09-27 15:15:34 +00:00
renovate 39d2776401 chore(deps): update dependency eslint-plugin-vue to v10.11.1 (#368)
schemas-app / build (push) Successful in 34s
schemas-app / deploy-prod (push) Successful in 1m17s
2026-09-27 02:16:01 +00:00
renovate ca70118877 chore(deps): update dependency jsdom to v30.1.1 (#367)
schemas-app / build (push) Successful in 1m5s
schemas-app / deploy-prod (push) Successful in 1m6s
2026-09-25 04:13:27 +00:00
renovate 3c8628897a chore(deps): update dependency typescript-eslint to v8.70.1 (#366)
schemas-app / build (push) Successful in 39s
schemas-app / deploy-prod (push) Successful in 1m15s
2026-09-24 18:15:58 +00:00
renovate 88883e21e6 chore(deps): update pre-commit hook alessandrojcm/commitlint-pre-commit-hook to v9.27.0 (#365)
schemas-app / build (push) Successful in 1m25s
schemas-app / deploy-prod (push) Successful in 1m11s
2026-09-23 19:31:51 +00:00
renovate ab17e4fbeb chore(deps): update graphqlcodegenerator monorepo (#364)
schemas-app / build (push) Successful in 58s
schemas-app / deploy-prod (push) Successful in 1m7s
2026-09-23 06:14:30 +00:00
renovate e66a8d8616 chore(deps): update commitlint monorepo to v21.2.3 (#363)
schemas-app / build (push) Successful in 59s
schemas-app / deploy-prod (push) Successful in 1m17s
2026-09-22 19:31:21 +00:00
renovate d6813456b7 chore(deps): update pre-commit hook pre-commit/mirrors-eslint to v10.11.0 (#362)
schemas-app / build (push) Successful in 44s
schemas-app / deploy-prod (push) Successful in 1m11s
2026-09-22 14:21:16 +00:00
renovate bb66632e4e chore(deps): update dependency eslint to v10.11.0 (#361)
schemas-app / build (push) Successful in 31s
schemas-app / deploy-prod (push) Successful in 1m8s
2026-09-21 22:19:56 +00:00
renovate f9695c55ee fix(deps): update dependency @auth0/auth0-vue to v2.10.0 (#360)
schemas-app / build (push) Successful in 2m25s
schemas-app / deploy-prod (push) Successful in 1m12s
2026-09-20 10:17:41 +00:00
renovate 05f6c09bf0 fix(deps): update dependency vue to v3.5.43 (#359)
schemas-app / build (push) Successful in 2m45s
schemas-app / deploy-prod (push) Successful in 1m12s
2026-09-20 10:17:23 +00:00
renovate 874fa1eb36 chore(deps): update dependency jsdom to v30.1.0 (#358)
schemas-app / build (push) Successful in 30s
schemas-app / deploy-prod (push) Successful in 1m5s
2026-09-20 02:19:17 +00:00
renovate e6ccbcc9ae fix(deps): update dependency graphql-ws to v6.2.2 (#357)
schemas-app / build (push) Successful in 2m58s
schemas-app / deploy-prod (push) Successful in 1m21s
2026-09-19 15:36:44 +00:00
renovate 9a64ba985f chore(deps): update dependency @vue/test-utils to v2.5.1 (#356)
schemas-app / build (push) Successful in 35s
schemas-app / deploy-prod (push) Successful in 1m17s
2026-09-19 10:19:11 +00:00
renovate 488f996390 chore(deps): update nginx:1.31.6 docker digest to 8e1fce8 (#355)
schemas-app / build (push) Successful in 33s
schemas-app / deploy-prod (push) Successful in 1m8s
2026-09-19 02:17:07 +00:00
renovate 924d0aee21 chore(deps): update vitest monorepo to v5.0.1 (#354)
schemas-app / build (push) Successful in 38s
schemas-app / deploy-prod (push) Successful in 1m19s
2026-09-18 09:18:30 +00:00
renovate fc030da514 chore(deps): update dependency @vitejs/plugin-vue to v6.0.9 (#353)
schemas-app / build (push) Successful in 1m31s
schemas-app / deploy-prod (push) Successful in 1m33s
2026-09-17 07:42:49 +00:00
renovate 0831783818 chore(deps): update nginx docker tag to v1.31.6 (#352)
schemas-app / build (push) Successful in 1m2s
schemas-app / deploy-prod (push) Successful in 1m12s
2026-09-16 01:15:40 +00:00
11 changed files with 2198 additions and 2084 deletions

No files matched your search

+18 -4
View File
@@ -18,16 +18,30 @@ jobs:
- name: Build and push
run: unset GITEA_TOKEN && build && push
deploy-prod:
deploy-prod-frostmoln:
needs: build
if: gitea.ref == 'refs/heads/main'
runs-on: ubuntu-latest
env:
BUILDTOOLS_CONTENT: ${{ secrets.BUILDTOOLS_CONTENT }}
BUILDTOOLS_CONTENT: ${{ secrets.BUILDTOOLS_FROSTMOLN_PRODUCTION }}
GITEA_REPOSITORY: ${{ gitea.repository }}
FM_TENANT: 9ae61342-0f76-476f-8176-e46f6b0b0c32
environment: prod
steps:
- uses: actions/checkout@v7
- uses: buildtool/setup-buildtools-action@v1
- name: Deploy to production
run: deploy prod
- name: Install fm
run: |
sudo install -d -m 0755 /etc/apt/keyrings
sudo curl -fsSL -o /etc/apt/keyrings/frostmoln.gpg https://get.frostmoln.cloud/deb/frostmoln.gpg
sudo curl -fsSL -o /etc/apt/sources.list.d/frostmoln.sources https://get.frostmoln.cloud/deb/frostmoln.sources
sudo apt-get update && sudo apt-get install -y fm
- name: Deploy to Frostmoln production
env:
FROSTMOLN_API_KEY: ${{ secrets.FROSTMOLN_PRODUCTION_DEPLOY_KEY }}
# The cluster API is private: the kubeconfig's exec plugin opens an fm
# tunnel on demand. fm reads the key from its config file, not the env.
run: |
fm auth api-key set "$FROSTMOLN_API_KEY" > /dev/null
fm kubernetes cluster kubeconfig ${{ vars.FROSTMOLN_PRODUCTION_CLUSTER_ID }} --exec --file "$RUNNER_TEMP/kubeconfig"
KUBECONFIG_CONTENT="$(cat "$RUNNER_TEMP/kubeconfig")" deploy prod-frostmoln -n schemas
+2 -2
View File
@@ -22,13 +22,13 @@ repos:
- --project
- unboundsoftware/schemas-app
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.26.0
rev: v9.27.0
hooks:
- id: commitlint
stages: [ commit-msg ]
additional_dependencies: [ '@commitlint/config-conventional' ]
- repo: https://github.com/pre-commit/mirrors-eslint
rev: v10.10.0
rev: v10.12.0
hooks:
- id: eslint
types: [ file ]
+4 -3
View File
@@ -12,9 +12,10 @@ RUN npm run postinstall && npm run generate && npm run lint && npm run test:cove
FROM scratch as export
COPY --from=builder /build/coverage /
FROM amd64/nginx:1.31.5@sha256:e9edb980c805d3c55dfbb73a88bf0340697a6643661757cf656b0d48ca118873
# Unprivileged (uid 101, port 8080): Frostmoln enforces restricted Pod Security.
FROM nginxinc/nginx-unprivileged:1.31.6@sha256:1d26a516fb93b18f9c0214dc9c645054486e516f13ff09ef63d5bd5c622278a2
MAINTAINER Joakim Olsson <joakim@unbound.se>
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY ./nginx/security_headers.conf /etc/nginx/security_headers.conf
COPY --chmod=644 ./nginx/nginx.conf /etc/nginx/nginx.conf
COPY --chmod=644 ./nginx/security_headers.conf /etc/nginx/security_headers.conf
COPY --from=builder /build/.output/public/ /usr/share/nginx/html/
File renamed without changes.
+14 -6
View File
@@ -23,6 +23,11 @@ spec:
app.kubernetes.io/name: schemas-app
app.kubernetes.io/instance: schemas
spec:
securityContext:
runAsNonRoot: true
runAsUser: 101
seccompProfile:
type: RuntimeDefault
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
@@ -37,21 +42,25 @@ spec:
topologyKey: kubernetes.io/hostname
containers:
- name: schemas-app
image: oci.unbound.se/unboundsoftware/schemas-app:${COMMIT}
image: ${IMAGE}
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
ports:
- containerPort: 80
- containerPort: 8080
readinessProbe:
httpGet:
path: /
port: 80
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 5
livenessProbe:
httpGet:
path: /
port: 80
port: 8080
initialDelaySeconds: 10
periodSeconds: 10
timeoutSeconds: 5
@@ -71,9 +80,8 @@ metadata:
labels:
app.kubernetes.io/name: schemas-app
spec:
type: NodePort
selector:
app.kubernetes.io/name: schemas-app
ports:
- port: 80
targetPort: 80
targetPort: 8080
+21
View File
@@ -0,0 +1,21 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: schemas-app
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls.certresolver: letsencrypt
spec:
ingressClassName: traefik
rules:
- host: "schemas.unbound.se"
http:
paths:
# Everything but /query, which the schemas API's longer path takes.
- path: /
pathType: Prefix
backend:
service:
name: schemas-app
port:
number: 80
-25
View File
@@ -1,25 +0,0 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: schemas-app-ingress
annotations:
alb.ingress.kubernetes.io/group.name: "default"
alb.ingress.kubernetes.io/group.order: "15"
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: instance
alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80},{"HTTPS": 443}]'
alb.ingress.kubernetes.io/ssl-redirect: "443"
alb.ingress.kubernetes.io/healthcheck-path: '/'
spec:
ingressClassName: "alb"
rules:
- host: "schemas.unbound.se"
http:
paths:
- path: /*
pathType: ImplementationSpecific
backend:
service:
name: schemas-app
port:
number: 80
File renamed without changes.
+9 -3
View File
@@ -1,14 +1,20 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
}
http {
# Writable by the unprivileged (uid 101) worker.
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp_path;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
include /etc/nginx/mime.types;
default_type application/octet-stream;
types {
@@ -22,7 +28,7 @@ http {
keepalive_timeout 65;
server {
listen 80;
listen 8080;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
+2111 -2022
View File
File diff suppressed because it is too large. Load diff
+19 -19
View File
@@ -19,12 +19,12 @@
},
"dependencies": {
"@apollo/client": "3.14.1",
"@auth0/auth0-vue": "2.9.0",
"@auth0/auth0-vue": "2.11.0",
"@vue/apollo-composable": "4.2.2",
"graphql": "16.14.2",
"graphql-ws": "6.2.1",
"nuxt": "4.5.2",
"vue": "3.5.42",
"graphql-ws": "6.3.0",
"nuxt": "4.6.1",
"vue": "3.5.43",
"vuetify-nuxt-module": "0.19.5"
},
"version": "1.0.0",
@@ -34,31 +34,31 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@commitlint/cli": "21.2.2",
"@commitlint/config-conventional": "21.2.2",
"@graphql-codegen/cli": "7.4.1",
"@graphql-codegen/typed-document-node": "7.1.0",
"@graphql-codegen/typescript": "6.1.0",
"@graphql-codegen/typescript-operations": "6.1.6",
"@commitlint/cli": "21.2.3",
"@commitlint/config-conventional": "21.2.3",
"@graphql-codegen/cli": "7.4.6",
"@graphql-codegen/typed-document-node": "7.1.1",
"@graphql-codegen/typescript": "6.1.2",
"@graphql-codegen/typescript-operations": "6.1.10",
"@graphql-codegen/typescript-vue-apollo": "5.0.1",
"@nuxt/devtools": "3.4.2",
"@nuxt/eslint": "1.17.0",
"@nuxtjs/stylelint-module": "5.2.1",
"@stylistic/eslint-plugin": "5.10.0",
"@vitejs/plugin-vue": "6.0.8",
"@vitest/coverage-v8": "5.0.0",
"@vue/test-utils": "2.5.0",
"eslint": "10.10.0",
"@vitejs/plugin-vue": "6.0.10",
"@vitest/coverage-v8": "5.0.3",
"@vue/test-utils": "2.5.1",
"eslint": "10.12.0",
"eslint-plugin-simple-import-sort": "14.0.0",
"eslint-plugin-vue": "10.11.0",
"jsdom": "30.0.1",
"eslint-plugin-vue": "10.11.1",
"jsdom": "30.1.2",
"postcss-html": "2.0.0",
"stylelint": "17.15.0",
"stylelint": "17.16.0",
"stylelint-config-recommended-vue": "2.0.0",
"stylelint-config-standard": "40.0.0",
"typescript": "6.0.3",
"typescript-eslint": "8.70.0",
"vitest": "5.0.0",
"typescript-eslint": "8.71.1",
"vitest": "5.0.3",
"vue-eslint-parser": "10.4.1"
},
"overrides": {