refactor: replace generate-job.py with nomad-job.nix, add flake-output input
Use nix eval --raw --impure + builtins.getEnv instead of Python for Nomad job JSON generation. Add flake-output input (default: default) so projects can build non-default outputs like docs. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
95bf5517f7
commit
4af132296e
3 changed files with 96 additions and 110 deletions
|
|
@ -11,6 +11,11 @@ inputs:
|
|||
description: 'Domain the site is served at (e.g. toph.so)'
|
||||
required: true
|
||||
|
||||
flake-output:
|
||||
description: 'Flake output to build (e.g. default, docs)'
|
||||
required: false
|
||||
default: 'default'
|
||||
|
||||
nomad-addr:
|
||||
description: 'Nomad API address'
|
||||
required: false
|
||||
|
|
@ -50,7 +55,7 @@ runs:
|
|||
|
||||
- name: Build site
|
||||
shell: bash
|
||||
run: nix build .#default --out-link result-site
|
||||
run: nix build ".#${{ inputs.flake-output }}" --out-link result-site
|
||||
|
||||
- name: Sign and push Nix closure to S3 cache
|
||||
shell: bash
|
||||
|
|
@ -76,10 +81,13 @@ runs:
|
|||
- name: Deploy Nomad job
|
||||
shell: bash
|
||||
run: |
|
||||
python3 "${{ github.action_path }}/generate-job.py" | nomad job run -json -
|
||||
nix eval --raw --impure \
|
||||
--expr "import ${{ github.action_path }}/nomad-job.nix" \
|
||||
| nomad job run -json -
|
||||
env:
|
||||
NOMAD_ADDR: ${{ inputs.nomad-addr }}
|
||||
DOMAIN: ${{ inputs.domain }}
|
||||
SITE_HASH: ${{ env.SITE_HASH }}
|
||||
SERVER_IMAGE: ${{ inputs.server-image }}
|
||||
DATACENTER: ${{ inputs.datacenter }}
|
||||
S3_BUCKET: ${{ inputs.s3-bucket }}
|
||||
|
|
|
|||
|
|
@ -1,108 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Generate a Nomad job JSON for a static site deployment.
|
||||
Reads from environment variables, prints JSON to stdout.
|
||||
Pipe to: nomad job run -json -
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
domain = os.environ["DOMAIN"]
|
||||
site_hash = os.environ["SITE_HASH"]
|
||||
server_image = os.environ.get("SERVER_IMAGE", "registry.toph.so/static-server:latest")
|
||||
datacenter = os.environ.get("DATACENTER", "contabo")
|
||||
s3_bucket = os.environ["S3_BUCKET"]
|
||||
|
||||
job_id = "site-" + domain.replace(".", "-")
|
||||
|
||||
startup_cmd = (
|
||||
f"mkdir -p /var/www && "
|
||||
f"aws s3 cp s3://{s3_bucket}/sites/{domain}/{site_hash}.tar.gz - "
|
||||
f"| tar xz -C /var/www/ && "
|
||||
f"exec static-web-server --port 8080 --root /var/www"
|
||||
)
|
||||
|
||||
nomad_template_data = (
|
||||
'{{ with nomadVar "static-sites/s3" }}'
|
||||
"AWS_ACCESS_KEY_ID={{ .access_key }}\n"
|
||||
"AWS_SECRET_ACCESS_KEY={{ .secret_key }}\n"
|
||||
"AWS_ENDPOINT_URL={{ .endpoint }}\n"
|
||||
"{{ end }}"
|
||||
)
|
||||
|
||||
job = {
|
||||
"Job": {
|
||||
"ID": job_id,
|
||||
"Name": job_id,
|
||||
"Namespace": "static-sites",
|
||||
"Type": "service",
|
||||
"Datacenters": [datacenter],
|
||||
"Update": {
|
||||
"MinHealthyTime": 5000000000, # 5s in nanoseconds
|
||||
"HealthyDeadline": 60000000000, # 60s in nanoseconds
|
||||
"MaxParallel": 1,
|
||||
},
|
||||
"TaskGroups": [
|
||||
{
|
||||
"Name": "site",
|
||||
"Count": 1,
|
||||
"Networks": [
|
||||
{
|
||||
"DynamicPorts": [
|
||||
{"Label": "http", "To": 8080}
|
||||
]
|
||||
}
|
||||
],
|
||||
"Services": [
|
||||
{
|
||||
"Name": job_id,
|
||||
"Provider": "nomad",
|
||||
"PortLabel": "http",
|
||||
"Tags": [
|
||||
"traefik.enable=true",
|
||||
f"traefik.http.routers.{job_id}.rule=Host(`{domain}`)",
|
||||
f"traefik.http.routers.{job_id}.entrypoints=websecure",
|
||||
f"traefik.http.routers.{job_id}.tls.certresolver=letsencrypt",
|
||||
],
|
||||
"Checks": [
|
||||
{
|
||||
"Type": "http",
|
||||
"Path": "/",
|
||||
"Interval": 30000000000, # 30s
|
||||
"Timeout": 5000000000, # 5s
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
"Tasks": [
|
||||
{
|
||||
"Name": "server",
|
||||
"Driver": "docker",
|
||||
"Config": {
|
||||
"image": server_image,
|
||||
"command": "/bin/bash",
|
||||
"args": ["-c", startup_cmd],
|
||||
"ports": ["http"],
|
||||
},
|
||||
"Templates": [
|
||||
{
|
||||
"EmbeddedTmpl": nomad_template_data,
|
||||
"DestPath": "secrets/s3.env",
|
||||
"Envvars": True,
|
||||
}
|
||||
],
|
||||
"Resources": {
|
||||
"CPU": 100,
|
||||
"MemoryMB": 128,
|
||||
},
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
json.dump(job, sys.stdout, indent=2)
|
||||
print()
|
||||
86
deploy-static-site/nomad-job.nix
Normal file
86
deploy-static-site/nomad-job.nix
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
let
|
||||
domain = builtins.getEnv "DOMAIN";
|
||||
siteHash = builtins.getEnv "SITE_HASH";
|
||||
serverImage = builtins.getEnv "SERVER_IMAGE";
|
||||
datacenter = builtins.getEnv "DATACENTER";
|
||||
s3Bucket = builtins.getEnv "S3_BUCKET";
|
||||
|
||||
jobId = "site-" + builtins.replaceStrings [ "." ] [ "-" ] domain;
|
||||
|
||||
startupCmd =
|
||||
"mkdir -p /var/www && " +
|
||||
"aws s3 cp s3://${s3Bucket}/sites/${domain}/${siteHash}.tar.gz - " +
|
||||
"| tar xz -C /var/www/ && " +
|
||||
"exec static-web-server --port 8080 --root /var/www";
|
||||
|
||||
templateData =
|
||||
"{{ with nomadVar \"static-sites/s3\" }}" +
|
||||
"AWS_ACCESS_KEY_ID={{ .access_key }}\n" +
|
||||
"AWS_SECRET_ACCESS_KEY={{ .secret_key }}\n" +
|
||||
"AWS_ENDPOINT_URL={{ .endpoint }}\n" +
|
||||
"{{ end }}";
|
||||
|
||||
job = {
|
||||
Job = {
|
||||
ID = jobId;
|
||||
Name = jobId;
|
||||
Namespace = "static-sites";
|
||||
Type = "service";
|
||||
Datacenters = [ datacenter ];
|
||||
Update = {
|
||||
MinHealthyTime = 5000000000;
|
||||
HealthyDeadline = 60000000000;
|
||||
MaxParallel = 1;
|
||||
};
|
||||
TaskGroups = [
|
||||
{
|
||||
Name = "site";
|
||||
Count = 1;
|
||||
Networks = [
|
||||
{ DynamicPorts = [ { Label = "http"; To = 8080; } ]; }
|
||||
];
|
||||
Services = [
|
||||
{
|
||||
Name = jobId;
|
||||
Provider = "nomad";
|
||||
PortLabel = "http";
|
||||
Tags = [
|
||||
"traefik.enable=true"
|
||||
"traefik.http.routers.${jobId}.rule=Host(`${domain}`)"
|
||||
"traefik.http.routers.${jobId}.entrypoints=websecure"
|
||||
"traefik.http.routers.${jobId}.tls.certresolver=letsencrypt"
|
||||
];
|
||||
Checks = [
|
||||
{ Type = "http"; Path = "/"; Interval = 30000000000; Timeout = 5000000000; }
|
||||
];
|
||||
}
|
||||
];
|
||||
Tasks = [
|
||||
{
|
||||
Name = "server";
|
||||
Driver = "docker";
|
||||
Config = {
|
||||
image = serverImage;
|
||||
command = "/bin/bash";
|
||||
args = [ "-c" startupCmd ];
|
||||
ports = [ "http" ];
|
||||
};
|
||||
Templates = [
|
||||
{
|
||||
EmbeddedTmpl = templateData;
|
||||
DestPath = "secrets/s3.env";
|
||||
Envvars = true;
|
||||
}
|
||||
];
|
||||
Resources = {
|
||||
CPU = 100;
|
||||
MemoryMB = 128;
|
||||
};
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
in
|
||||
builtins.toJSON job
|
||||
Loading…
Add table
Reference in a new issue