The review finishes before the push and its record is a Reviewed-by line in the description, so the mark repeated what the push meant. mesh-delivery asks the operator when a pull request's checks pass, keeps an ask through a trunk move by asking the check again at once, and hands the merge tool the approved heads, which replace the forge review of each sibling.
500 lines
13 KiB
JSON
500 lines
13 KiB
JSON
{
|
|
"module": "gitea",
|
|
"version": "1",
|
|
"moved": true,
|
|
"requires": [
|
|
"postgres-database",
|
|
"route",
|
|
"secret"
|
|
],
|
|
"contributes": {
|
|
"postgres-database": {
|
|
"name": "gitea"
|
|
},
|
|
"route": {
|
|
"web": {
|
|
"label": "git",
|
|
"endpoint": "web"
|
|
},
|
|
"internal-api-refused": {
|
|
"label": "git",
|
|
"path": "/api/internal",
|
|
"deny": true,
|
|
"priority": 100000
|
|
}
|
|
}
|
|
},
|
|
"binds": {
|
|
"postgres-database": "${dir:state}/database.json",
|
|
"route": "${dir:state}/route.json"
|
|
},
|
|
"secrets": {
|
|
"postgres-database": "${dir:state}/database.secret",
|
|
"secret": {
|
|
"internal-token": "${dir:state}/internal-token.secret",
|
|
"admin": "${dir:state}/admin.secret"
|
|
}
|
|
},
|
|
"capabilities": [
|
|
"container-runtime"
|
|
],
|
|
"emits": [
|
|
"repo.created",
|
|
"issue.opened",
|
|
"pull.merged",
|
|
"pull.updated",
|
|
"pull.closed",
|
|
"forge.push",
|
|
"forge.create",
|
|
"forge.delete",
|
|
"forge.fork",
|
|
"forge.status",
|
|
"forge.pull-request.opened",
|
|
"forge.pull-request.reopened",
|
|
"forge.pull-request.synchronized",
|
|
"forge.pull-request.edited",
|
|
"forge.pull-request.closed",
|
|
"forge.pull-request.merged",
|
|
"forge.pull-request.labeled",
|
|
"forge.pull-request.unlabeled",
|
|
"forge.pull-request.assigned",
|
|
"forge.pull-request.unassigned",
|
|
"forge.pull-request.reviewed",
|
|
"forge.pull-request.review-requested",
|
|
"forge.pull-request.commented",
|
|
"forge.pull-request.changed",
|
|
"forge.issue-comment.created",
|
|
"forge.issue-comment.edited",
|
|
"forge.issue-comment.deleted",
|
|
"forge.issues.opened",
|
|
"forge.issues.reopened",
|
|
"forge.issues.closed",
|
|
"forge.issues.edited",
|
|
"forge.issues.labeled",
|
|
"forge.issues.unlabeled",
|
|
"forge.issues.assigned",
|
|
"forge.issues.unassigned",
|
|
"forge.issues.changed",
|
|
"forge.release.published",
|
|
"forge.release.updated",
|
|
"forge.release.deleted",
|
|
"forge.release.changed",
|
|
"forge.repository.created",
|
|
"forge.repository.deleted",
|
|
"forge.repository.changed",
|
|
"forge.wiki.changed",
|
|
"forge.other"
|
|
],
|
|
"consumes": [
|
|
"mesh-controller.checked",
|
|
"node-build-agent.started"
|
|
],
|
|
"listens": [
|
|
{
|
|
"name": "web",
|
|
"port": 3000,
|
|
"protocol": "tcp",
|
|
"from": "mesh",
|
|
"why": "the forge, over http"
|
|
},
|
|
{
|
|
"name": "ssh",
|
|
"port": 22,
|
|
"protocol": "tcp",
|
|
"from": "mesh",
|
|
"why": "git over ssh, gitea's own unmodified sshd. Published on the machine's own side at 222, the mesh's fixed public convention — not 22, which the machine's own daemon holds and a module does not take"
|
|
},
|
|
{
|
|
"name": "forge-events",
|
|
"port": 3047,
|
|
"protocol": "tcp",
|
|
"from": "machine",
|
|
"why": "the forge's system webhook, every event signed with a secret the module keeps, from the forge's container on the docker bridge to the module's receiver at the bridge's gateway 172.17.0.1 (novox/hq issue 729)"
|
|
}
|
|
],
|
|
"serves": {
|
|
"npm-package-registry": {
|
|
"scheme": "http",
|
|
"port": 3000,
|
|
"npm-path": "/api/packages/novox/npm/",
|
|
"public-root": "https://${bound:route:name-web}/api/packages/novox/npm/"
|
|
},
|
|
"git": {
|
|
"scheme": "http",
|
|
"port": 3000
|
|
}
|
|
},
|
|
"receives": {
|
|
"npm-package-registry": "${dir:grants}/npm.json"
|
|
},
|
|
"grants": {
|
|
"npm-package-registry": "${dir:grants}"
|
|
},
|
|
"claims": [
|
|
{
|
|
"name": "npm-package-registry",
|
|
"scope": "mesh"
|
|
},
|
|
{
|
|
"name": "git",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"data": {
|
|
"own": [
|
|
{
|
|
"id": "data",
|
|
"path": "${dir:data}",
|
|
"class": "valuable",
|
|
"why": "every repository, its issues and attachments, and the package registry"
|
|
}
|
|
],
|
|
"consumers": {
|
|
"npm-package-registry": {
|
|
"class": "rebuildable",
|
|
"in": "data",
|
|
"why": "a consumer's packages are published again from its source"
|
|
}
|
|
}
|
|
},
|
|
"config": {
|
|
"url": {
|
|
"type": "string",
|
|
"description": "The address the module's tools reach the forge at, as a URL; unset, the code falls back to its environment, else this machine's gitea on its port.",
|
|
"trusted": true,
|
|
"default": ""
|
|
},
|
|
"agent-read-teams": {
|
|
"type": "object",
|
|
"description": "The read teams of the agents' forge accounts (ADR 0365 clause 3): each team by name, {\"<team>\": {\"repos\": [\"<owner>/<repo>\", ...], \"members\": [\"<node>\", ...]}}. The forge gets a team agent-read-<team> that reads only, with exactly those repositories and the accounts agent-<node>; a team taken out of the value is emptied. Nothing else on the forge is touched; an agent account is in no team until it is listed here.",
|
|
"trusted": true,
|
|
"default": {}
|
|
}
|
|
},
|
|
"facts": {
|
|
"forge-host": {
|
|
"path": "/etc/gitea/forge-host",
|
|
"template": "{{range .Machines}}{{if eq .Name $.Node}}{{.FQDN}}{{end}}{{end}}\n"
|
|
}
|
|
},
|
|
"resources": [
|
|
{
|
|
"id": "mesh-state",
|
|
"type": "directory",
|
|
"mode": "0700",
|
|
"place": "mesh",
|
|
"unknown": "program"
|
|
},
|
|
{
|
|
"id": "runtime-state",
|
|
"type": "directory",
|
|
"path": "${dir:mesh-state}/state",
|
|
"mode": "0700",
|
|
"unknown": "program"
|
|
},
|
|
{
|
|
"id": "forge-patches",
|
|
"type": "directory",
|
|
"path": "/var/lib/mesh/forge-patches",
|
|
"mode": "0733",
|
|
"owner": "${machine:account}",
|
|
"unknown": "program"
|
|
},
|
|
{
|
|
"id": "state",
|
|
"type": "directory",
|
|
"mode": "0700",
|
|
"place": ".",
|
|
"unknown": "program"
|
|
},
|
|
{
|
|
"id": "grants",
|
|
"type": "directory",
|
|
"mode": "0700",
|
|
"unknown": "program"
|
|
},
|
|
{
|
|
"id": "server-env",
|
|
"type": "file",
|
|
"path": "${dir:state}/server.env",
|
|
"mode": "0600",
|
|
"template": "files/server.env"
|
|
},
|
|
{
|
|
"id": "data",
|
|
"type": "directory",
|
|
"mode": "0700",
|
|
"owner": "1000:1000",
|
|
"unknown": "program"
|
|
},
|
|
{
|
|
"id": "server",
|
|
"type": "container",
|
|
"health": {
|
|
"kind": "http",
|
|
"endpoint": "web",
|
|
"path": "/api/healthz",
|
|
"status": 200,
|
|
"needs": "postgres-database"
|
|
},
|
|
"name": "gitea",
|
|
"image": "gitea/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef",
|
|
"env": {
|
|
"DB_TYPE": "postgres",
|
|
"USER_UID": "1000",
|
|
"USER_GID": "1000"
|
|
},
|
|
"env-file": [
|
|
"${dir:state}/server.env"
|
|
],
|
|
"ports": [
|
|
"3000",
|
|
"222:22"
|
|
],
|
|
"volumes": [
|
|
"${dir:data}:/data"
|
|
],
|
|
"secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it",
|
|
"logging": "journald"
|
|
},
|
|
{
|
|
"id": "admin-bootstrap",
|
|
"type": "container",
|
|
"name": "mesh-gitea-admin",
|
|
"image": "gitea/gitea@sha256:87a67ee09d3ae0d1df5fda5dcda3e2a1f9236a45b0a59025d6e00e46adc43bef",
|
|
"run-once": true,
|
|
"env": {
|
|
"USER_UID": "1000",
|
|
"USER_GID": "1000",
|
|
"MESH_GITEA_ADMIN_USER": "mesh-admin"
|
|
},
|
|
"env-file": [
|
|
"${dir:state}/server.env"
|
|
],
|
|
"volumes": [
|
|
"${dir:data}:/data",
|
|
"${dir:state}/admin.secret:/run/secrets/admin:ro"
|
|
],
|
|
"args": [
|
|
"/bin/sh",
|
|
"-c",
|
|
"su-exec git gitea admin user create --admin --username \"$MESH_GITEA_ADMIN_USER\" --email mesh-admin@localhost --password \"$(cat /run/secrets/admin)\" --must-change-password=false || true"
|
|
],
|
|
"secrets-in-environment": "gitea honours GITEA__database__PASSWD__FILE and GITEA__security__INTERNAL_TOKEN__FILE; convertible, awaiting a bed that proves it"
|
|
},
|
|
{
|
|
"id": "origins",
|
|
"type": "file",
|
|
"path": "${dir:mesh-state}/origins",
|
|
"mode": "0644",
|
|
"template": "files/origins"
|
|
},
|
|
{
|
|
"id": "runtime-config",
|
|
"type": "file",
|
|
"path": "${dir:mesh-state}/config.json",
|
|
"mode": "0600",
|
|
"template": "files/config.json",
|
|
"merge": "json",
|
|
"takes-config": [
|
|
"url"
|
|
]
|
|
},
|
|
{
|
|
"id": "agent-teams-file",
|
|
"type": "file",
|
|
"path": "${dir:mesh-state}/agent-teams.json",
|
|
"mode": "0600",
|
|
"template": "files/agent-teams.json",
|
|
"merge": "json",
|
|
"takes-config": [
|
|
"agent-read-teams"
|
|
]
|
|
},
|
|
{
|
|
"id": "consumers",
|
|
"type": "file",
|
|
"path": "${dir:state}/consumers.json",
|
|
"mode": "0600",
|
|
"template": "files/consumers.json"
|
|
},
|
|
{
|
|
"id": "agent-teams",
|
|
"type": "process",
|
|
"name": "gitea-agent-teams",
|
|
"artifact": "agent-teams",
|
|
"run": [
|
|
"./agent-teams"
|
|
],
|
|
"run-once": true,
|
|
"env": {
|
|
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
|
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
|
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
|
"MESH_AGENT_TEAMS_FILE": "${dir:mesh-state}/agent-teams.json"
|
|
},
|
|
"restart-on": [
|
|
"agent-teams-file"
|
|
]
|
|
}
|
|
],
|
|
"provides": [
|
|
{
|
|
"name": "npm-package-registry",
|
|
"scope": "mesh",
|
|
"identity": {
|
|
"max": 40,
|
|
"in": "a Gitea user name"
|
|
}
|
|
},
|
|
{
|
|
"name": "git",
|
|
"scope": "mesh"
|
|
},
|
|
{
|
|
"name": "gitea-read",
|
|
"scope": "mesh",
|
|
"credential": {
|
|
"issued-by": "software",
|
|
"tool": "gitea_agent_token"
|
|
}
|
|
},
|
|
{
|
|
"name": "forge-account",
|
|
"scope": "mesh"
|
|
}
|
|
],
|
|
"build": {
|
|
"artifacts": [
|
|
{
|
|
"name": "code",
|
|
"kind": "bundle",
|
|
"language": "typescript",
|
|
"entrypoints": [
|
|
"index.js",
|
|
"tools/index.js",
|
|
"provisioner/index.js"
|
|
],
|
|
"loads": [
|
|
"index.js",
|
|
"tools/index.js",
|
|
"provisioner/index.js"
|
|
],
|
|
"env": {
|
|
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
|
"MESH_GITEA_CONFIG_FILE": "${dir:mesh-state}/config.json",
|
|
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
|
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
|
"MESH_GITEA_TOOLS_USER": "mesh-tools",
|
|
"MESH_GITEA_STATE_DIR": "${dir:runtime-state}",
|
|
"MESH_RECEIVES": "${dir:grants}/npm.json",
|
|
"MESH_GITEA_HOOK_URL": "http://172.17.0.1:3047",
|
|
"MESH_GITEA_HOOK_PORT": "3047",
|
|
"MESH_GITEA_HOOK_HOST": "172.17.0.1"
|
|
}
|
|
},
|
|
{
|
|
"name": "npm-registry",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/npm-registry",
|
|
"binary": "npm-registry",
|
|
"loads": [
|
|
"npm-registry"
|
|
],
|
|
"env": {
|
|
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
|
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
|
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
|
"MESH_NPM_OWNER": "novox"
|
|
}
|
|
},
|
|
{
|
|
"name": "forge",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/forge",
|
|
"binary": "forge",
|
|
"loads": [
|
|
"forge"
|
|
],
|
|
"env": {
|
|
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
|
"MESH_GITEA_TOOLS_USER": "mesh-tools",
|
|
"MESH_GITEA_TOKEN_FILE": "${dir:runtime-state}/token",
|
|
"MESH_GITEA_PATCH_DIR": "${dir:forge-patches}"
|
|
}
|
|
},
|
|
{
|
|
"name": "files",
|
|
"kind": "archive",
|
|
"from": "files"
|
|
},
|
|
{
|
|
"name": "agent-token",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/agent-token",
|
|
"binary": "agent-token",
|
|
"loads": [
|
|
"agent-token"
|
|
],
|
|
"env": {
|
|
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
|
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
|
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
|
"MESH_GITEA_ORIGINS_FILE": "${dir:mesh-state}/origins"
|
|
}
|
|
},
|
|
{
|
|
"name": "agent-teams",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/agent-teams",
|
|
"binary": "agent-teams",
|
|
"loads": [
|
|
"agent-teams"
|
|
]
|
|
},
|
|
{
|
|
"name": "forge-account-provider",
|
|
"kind": "bundle",
|
|
"language": "go",
|
|
"system": "arch",
|
|
"from": "cmd/forge-account-provider",
|
|
"binary": "forge-account-provider",
|
|
"loads": [
|
|
"forge-account-provider"
|
|
],
|
|
"env": {
|
|
"MESH_GITEA_URL": "http://127.0.0.1:${port:3000}",
|
|
"MESH_GITEA_ADMIN_USER": "mesh-admin",
|
|
"MESH_GITEA_ADMIN_PASSWORD_FILE": "${dir:state}/admin.secret",
|
|
"MESH_GITEA_ORIGINS_FILE": "${dir:mesh-state}/origins",
|
|
"MESH_GITEA_SSH_PORT": "222",
|
|
"MESH_FORGE_HOST_FILE": "/etc/gitea/forge-host"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"jails": [
|
|
{
|
|
"name": "gitea",
|
|
"failregex": "^.*Failed authentication attempt for .* from <HOST>(?::\\d+)?\\s*$\n ^.*Invalid user .* from <HOST> port \\d+\\s*$\n ^.*User \\S+ from <HOST> not allowed because .*$",
|
|
"jail": "backend = systemd\njournalmatch = CONTAINER_NAME=gitea\nport = http,https,222\nmaxretry = 3\nfindtime = 1d\nbantime = 1d"
|
|
}
|
|
],
|
|
"state": [
|
|
"bound",
|
|
"announced"
|
|
],
|
|
"reads": [
|
|
"mesh-controller.assignments",
|
|
"ssh-client.keys"
|
|
]
|
|
}
|