strip docker type — site-publish is static-content only
Removes type: docker handling from action.yaml, scripts (build/deploy/utils/setup), and templates (deployment.yaml.j2, service-docker.yaml.j2). Renamed service-static.yaml.j2 -> service.yaml.j2. If site.yaml has type: docker, parse_site_yaml() now dies with a clear message pointing to action/image-build + action/image-push + action/image-deploy with hand-authored apps-repo manifests. rainsounds.vino.network was the only docker consumer and has already migrated. Drops registry-password input from action.yaml (no longer needed).
This commit is contained in:
@@ -1,12 +1,20 @@
|
|||||||
# action/site-publish
|
# action/site-publish
|
||||||
|
|
||||||
Composite Gitea Action that publishes a website to the fritzlab k8s cluster.
|
Composite Gitea Action that publishes a **static-content** website to the
|
||||||
Supports `static`, `hugo`, `mkdocs` (content → Garage S3 + ExternalName Service)
|
fritzlab k8s cluster. Supports `static`, `hugo`, and `mkdocs`. Content goes
|
||||||
and `docker` (Dockerfile → Deployment + headless Service). Handles manifest
|
to a Garage S3 bucket; Traefik fronts the bucket via an `ExternalName`
|
||||||
rendering, TLS via cert-manager, and Garage bucket aliases.
|
Service with cert-manager TLS.
|
||||||
|
|
||||||
Renamed from `fritzlab/publish-site` → `action/site-publish` as part of the
|
> **Containerized web apps (Dockerfile-based) are NOT handled here.** Use the
|
||||||
2026 action-org consolidation.
|
> standard image-producer chain instead:
|
||||||
|
> [`action/image-build`](https://code.fritzlab.net/action/image-build) +
|
||||||
|
> [`action/image-push`](https://code.fritzlab.net/action/image-push) +
|
||||||
|
> [`action/image-deploy`](https://code.fritzlab.net/action/image-deploy).
|
||||||
|
> Hand-author the apps-repo manifests once (Deployment, Service, Ingress,
|
||||||
|
> Certificate, kustomization with `images:` block) and let `image-deploy`
|
||||||
|
> pin the tag on every push. See `sjc001/websites/rainsounds.vino.network/`
|
||||||
|
> for the canonical example. site-publish errors out explicitly if
|
||||||
|
> `site.yaml` has `type: docker`.
|
||||||
|
|
||||||
## Convention
|
## Convention
|
||||||
|
|
||||||
@@ -28,7 +36,7 @@ Or do it manually. `site.yaml`:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
domain: my-site.vino.network
|
domain: my-site.vino.network
|
||||||
type: static # static | hugo | mkdocs | docker
|
type: static # static | hugo | mkdocs
|
||||||
# content_dir: html # subdirectory containing content (default: repo root)
|
# content_dir: html # subdirectory containing content (default: repo root)
|
||||||
# aliases: # additional hostnames (each gets a globalAlias on the bucket)
|
# aliases: # additional hostnames (each gets a globalAlias on the bucket)
|
||||||
# - www.my-site.vino.network
|
# - www.my-site.vino.network
|
||||||
@@ -68,12 +76,11 @@ my-site.fritzlab.net 300 IN CNAME traefik.edge.svc.k8s.sjc001.fritzlab.net.
|
|||||||
| Input | Required | Default | Description |
|
| Input | Required | Default | Description |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `token` | yes | | Gitea token for apps repo push |
|
| `token` | yes | | Gitea token for apps repo push |
|
||||||
| `s3-access-key` | static/hugo/mkdocs | | Garage `ci-deploy-key` access key id |
|
| `s3-access-key` | yes | | Garage `ci-deploy-key` access key id |
|
||||||
| `s3-secret-key` | static/hugo/mkdocs | | Garage `ci-deploy-key` secret key |
|
| `s3-secret-key` | yes | | Garage `ci-deploy-key` secret key |
|
||||||
| `s3-endpoint` | no | `http://garage.storage.svc:3900` | Garage S3 endpoint |
|
| `s3-endpoint` | no | `http://garage.storage.svc:3900` | Garage S3 endpoint |
|
||||||
| `garage-admin-token` | static/hugo/mkdocs (only if site has `aliases`) | | Garage admin API token (`admin-token` from `garage-rpc-secret` in `storage` ns) |
|
| `garage-admin-token` | only if site has `aliases` | | Garage admin API token (`admin-token` from `garage-rpc-secret` in `storage` ns) |
|
||||||
| `garage-admin-endpoint` | no | `http://garage.storage.svc:3903` | Garage admin API endpoint |
|
| `garage-admin-endpoint` | no | `http://garage.storage.svc:3903` | Garage admin API endpoint |
|
||||||
| `registry-password` | docker | inputs.token | Container registry password |
|
|
||||||
| `username` | no | `ci-bot` | Gitea username |
|
| `username` | no | `ci-bot` | Gitea username |
|
||||||
|
|
||||||
Org secrets in `websites`: `CI_BOT_TOKEN`, `GARAGE_S3_ACCESS_KEY`,
|
Org secrets in `websites`: `CI_BOT_TOKEN`, `GARAGE_S3_ACCESS_KEY`,
|
||||||
@@ -105,3 +112,10 @@ There is no "first-deploy vs. update" branching — every deploy is idempotent.
|
|||||||
No nginx pods, no per-site Docker images. Garage matches `Host:` header to
|
No nginx pods, no per-site Docker images. Garage matches `Host:` header to
|
||||||
bucket name (or any of its globalAliases), so every site shares a single
|
bucket name (or any of its globalAliases), so every site shares a single
|
||||||
ExternalName target.
|
ExternalName target.
|
||||||
|
|
||||||
|
## History
|
||||||
|
|
||||||
|
- 2026-05-06: removed `type: docker` support. The single docker site
|
||||||
|
(`rainsounds.vino.network`) migrated to the `image-*` chain. site-publish
|
||||||
|
is now scoped strictly to static-content sites.
|
||||||
|
- 2026-05-06: renamed from `fritzlab/publish-site` → `action/site-publish`.
|
||||||
|
|||||||
+6
-10
@@ -1,24 +1,21 @@
|
|||||||
name: Publish Site
|
name: Publish Site
|
||||||
description: Build and deploy a site (static, hugo, mkdocs, or docker) to fritzlab k8s.
|
description: Build and deploy a static-content site (static, hugo, mkdocs) to Garage S3 with Traefik + cert-manager. Containerized apps should use action/image-build + action/image-push + action/image-deploy.
|
||||||
inputs:
|
inputs:
|
||||||
token:
|
token:
|
||||||
description: Gitea token (ci-bot) for apps repo push and API operations
|
description: Gitea token (ci-bot) for apps repo push and API operations
|
||||||
required: true
|
required: true
|
||||||
s3-access-key:
|
s3-access-key:
|
||||||
description: Garage ci-deploy-key access key id (required for static/hugo/mkdocs)
|
description: Garage ci-deploy-key access key id
|
||||||
required: false
|
required: true
|
||||||
s3-secret-key:
|
s3-secret-key:
|
||||||
description: Garage ci-deploy-key secret access key (required for static/hugo/mkdocs)
|
description: Garage ci-deploy-key secret access key
|
||||||
required: false
|
required: true
|
||||||
registry-password:
|
|
||||||
description: Container registry password (required for docker type; defaults to token)
|
|
||||||
required: false
|
|
||||||
s3-endpoint:
|
s3-endpoint:
|
||||||
description: Garage S3 endpoint URL
|
description: Garage S3 endpoint URL
|
||||||
required: false
|
required: false
|
||||||
default: http://garage.storage.svc:3900
|
default: http://garage.storage.svc:3900
|
||||||
garage-admin-token:
|
garage-admin-token:
|
||||||
description: Garage admin API token (required for static/hugo/mkdocs to reconcile bucket aliases)
|
description: Garage admin API token (required only when site.yaml has aliases — used to reconcile bucket globalAliases)
|
||||||
required: false
|
required: false
|
||||||
garage-admin-endpoint:
|
garage-admin-endpoint:
|
||||||
description: Garage admin API endpoint URL
|
description: Garage admin API endpoint URL
|
||||||
@@ -43,7 +40,6 @@ runs:
|
|||||||
SITE_DIR: ${{ github.workspace }}
|
SITE_DIR: ${{ github.workspace }}
|
||||||
ACTION_DIR: ${{ github.action_path }}
|
ACTION_DIR: ${{ github.action_path }}
|
||||||
GITHUB_RUN_NUMBER: ${{ github.run_number }}
|
GITHUB_RUN_NUMBER: ${{ github.run_number }}
|
||||||
REGISTRY_PASSWORD: ${{ inputs.registry-password || inputs.token }}
|
|
||||||
CI_BOT_USER: ${{ inputs.username }}
|
CI_BOT_USER: ${{ inputs.username }}
|
||||||
|
|
||||||
- name: Deploy
|
- name: Deploy
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3
-36
@@ -1,12 +1,11 @@
|
|||||||
"""Build phase — content prep (static) or docker image build."""
|
"""Build phase — content prep for static-content sites."""
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from utils import EXCLUDE_FILES, die, env, parse_site_yaml, run
|
from utils import EXCLUDE_FILES, env, parse_site_yaml, run
|
||||||
|
|
||||||
|
|
||||||
def build_static(site_dir, cfg):
|
def build_static(site_dir, cfg):
|
||||||
@@ -55,35 +54,6 @@ def build_static(site_dir, cfg):
|
|||||||
print(f"Build complete — content at {html_dir}")
|
print(f"Build complete — content at {html_dir}")
|
||||||
|
|
||||||
|
|
||||||
def docker_login():
|
|
||||||
password = os.environ.get("REGISTRY_PASSWORD", "")
|
|
||||||
user = env("CI_BOT_USER", "ci-bot")
|
|
||||||
if not password:
|
|
||||||
die("REGISTRY_PASSWORD is required for docker builds")
|
|
||||||
subprocess.run(
|
|
||||||
f"echo '{password}' | docker login code.fritzlab.net -u {user} --password-stdin",
|
|
||||||
shell=True, check=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def build_docker(site_dir, cfg):
|
|
||||||
docker_login()
|
|
||||||
image = cfg["image"]
|
|
||||||
run_number = env("GITHUB_RUN_NUMBER", "0")
|
|
||||||
tags = [f"{image}:latest", f"{image}:{run_number}"]
|
|
||||||
|
|
||||||
cmd_parts = ["docker", "build"]
|
|
||||||
for tag in tags:
|
|
||||||
cmd_parts += ["-t", tag]
|
|
||||||
cmd_parts += ["--network", "host", "--provenance=false"]
|
|
||||||
for key, val in cfg.get("build_args", {}).items():
|
|
||||||
cmd_parts += ["--build-arg", f"{key}={val}"]
|
|
||||||
cmd_parts.append(str(site_dir))
|
|
||||||
|
|
||||||
run(" ".join(cmd_parts))
|
|
||||||
print(f"Docker build complete — tags: {', '.join(tags)}")
|
|
||||||
|
|
||||||
|
|
||||||
def cmd_build():
|
def cmd_build():
|
||||||
site_dir = Path(env("SITE_DIR"))
|
site_dir = Path(env("SITE_DIR"))
|
||||||
cfg = parse_site_yaml(site_dir)
|
cfg = parse_site_yaml(site_dir)
|
||||||
@@ -92,7 +62,4 @@ def cmd_build():
|
|||||||
print("Site disabled — skipping build")
|
print("Site disabled — skipping build")
|
||||||
return
|
return
|
||||||
|
|
||||||
if cfg["type"] == "docker":
|
build_static(site_dir, cfg)
|
||||||
build_docker(site_dir, cfg)
|
|
||||||
else:
|
|
||||||
build_static(site_dir, cfg)
|
|
||||||
|
|||||||
+4
-90
@@ -1,9 +1,8 @@
|
|||||||
"""Deploy phase — S3 sync or docker push, manifest rendering, alias reconcile."""
|
"""Deploy phase — S3 sync, manifest rendering, alias reconcile."""
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.error import HTTPError, URLError
|
from urllib.error import HTTPError, URLError
|
||||||
@@ -108,62 +107,7 @@ def ensure_bucket_aliases(site_name, aliases, admin_token):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
||||||
def docker_push(cfg):
|
def render_site_manifests(site_name, action_dir, app_dir, manifests_dir, cfg):
|
||||||
image = cfg["image"]
|
|
||||||
run_number = env("GITHUB_RUN_NUMBER", "0")
|
|
||||||
for tag in [f"{image}:latest", f"{image}:{run_number}"]:
|
|
||||||
run(f"docker push {tag}")
|
|
||||||
|
|
||||||
|
|
||||||
def docker_tag_cleanup(cfg, token):
|
|
||||||
"""Keep the 3 newest numeric tags, delete the rest via Gitea API."""
|
|
||||||
image = cfg["image"]
|
|
||||||
parts = image.split("/")
|
|
||||||
if len(parts) < 3:
|
|
||||||
print(f"Cannot parse image for tag cleanup: {image}")
|
|
||||||
return
|
|
||||||
org = parts[1]
|
|
||||||
pkg_name = parts[2]
|
|
||||||
|
|
||||||
url = f"https://{GITEA_HOST}/api/v1/packages/{org}?type=container"
|
|
||||||
req = Request(url, headers={"Authorization": f"token {token}"})
|
|
||||||
try:
|
|
||||||
with urlopen(req) as resp:
|
|
||||||
packages = json.loads(resp.read())
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Warning: failed to list packages for cleanup: {e}")
|
|
||||||
return
|
|
||||||
|
|
||||||
numeric_versions = []
|
|
||||||
for pkg in packages:
|
|
||||||
if pkg.get("name") == pkg_name:
|
|
||||||
ver = pkg.get("version", "")
|
|
||||||
if ver.isdigit():
|
|
||||||
numeric_versions.append(int(ver))
|
|
||||||
|
|
||||||
numeric_versions.sort()
|
|
||||||
to_delete = numeric_versions[:-3] if len(numeric_versions) > 3 else []
|
|
||||||
|
|
||||||
for ver in to_delete:
|
|
||||||
del_url = f"https://{GITEA_HOST}/api/v1/packages/{org}/container/{pkg_name}/{ver}"
|
|
||||||
print(f" Deleting {pkg_name}:{ver}")
|
|
||||||
req = Request(del_url, method="DELETE", headers={"Authorization": f"token {token}"})
|
|
||||||
try:
|
|
||||||
urlopen(req)
|
|
||||||
except Exception as e:
|
|
||||||
print(f" Warning: failed to delete {pkg_name}:{ver}: {e}")
|
|
||||||
|
|
||||||
if to_delete:
|
|
||||||
print(f" Cleaned up {len(to_delete)} old tags")
|
|
||||||
else:
|
|
||||||
print(" No old tags to clean up")
|
|
||||||
|
|
||||||
|
|
||||||
def docker_cleanup():
|
|
||||||
run("docker system prune --all --force")
|
|
||||||
|
|
||||||
|
|
||||||
def render_site_manifests(site_name, action_dir, app_dir, manifests_dir, cfg, extra=None):
|
|
||||||
"""Always re-render manifests from current site.yaml. Templates own
|
"""Always re-render manifests from current site.yaml. Templates own
|
||||||
domain + aliases, so changes propagate without manual edits."""
|
domain + aliases, so changes propagate without manual edits."""
|
||||||
manifests_dir.mkdir(parents=True, exist_ok=True)
|
manifests_dir.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -173,11 +117,8 @@ def render_site_manifests(site_name, action_dir, app_dir, manifests_dir, cfg, ex
|
|||||||
"domain": cfg["domain"],
|
"domain": cfg["domain"],
|
||||||
"aliases": cfg["aliases"],
|
"aliases": cfg["aliases"],
|
||||||
"namespace": NAMESPACE,
|
"namespace": NAMESPACE,
|
||||||
"site_type": cfg["type"],
|
|
||||||
}
|
}
|
||||||
if extra:
|
render_templates(action_dir, template_vars, app_dir, manifests_dir)
|
||||||
template_vars.update(extra)
|
|
||||||
render_templates(action_dir, template_vars, app_dir, manifests_dir, cfg["type"])
|
|
||||||
|
|
||||||
|
|
||||||
def deploy_static(site_name, site_dir, action_dir, token, cfg):
|
def deploy_static(site_name, site_dir, action_dir, token, cfg):
|
||||||
@@ -193,30 +134,6 @@ def deploy_static(site_name, site_dir, action_dir, token, cfg):
|
|||||||
commit_and_push(apps_dir, f"Deploy {site_name}")
|
commit_and_push(apps_dir, f"Deploy {site_name}")
|
||||||
|
|
||||||
|
|
||||||
def deploy_docker(site_name, site_dir, action_dir, token, cfg):
|
|
||||||
docker_push(cfg)
|
|
||||||
|
|
||||||
run_number = env("GITHUB_RUN_NUMBER", "0")
|
|
||||||
image = cfg["image"]
|
|
||||||
apps_dir = clone_apps(token)
|
|
||||||
app_dir = apps_dir / "sjc001" / "websites" / site_name
|
|
||||||
manifests_dir = app_dir / "manifests"
|
|
||||||
|
|
||||||
render_site_manifests(site_name, action_dir, app_dir, manifests_dir, cfg, extra={
|
|
||||||
"image": image,
|
|
||||||
"port": cfg["port"],
|
|
||||||
"health_path": cfg["health_path"],
|
|
||||||
"replicas": cfg["replicas"],
|
|
||||||
})
|
|
||||||
# Pin to this build's tag (kustomize edit appends an `images:` override).
|
|
||||||
run(f"cd {manifests_dir} && kustomize edit set image {image}={image}:{run_number}")
|
|
||||||
|
|
||||||
commit_and_push(apps_dir, f"Deploy {site_name} #{run_number}")
|
|
||||||
|
|
||||||
docker_tag_cleanup(cfg, token)
|
|
||||||
docker_cleanup()
|
|
||||||
|
|
||||||
|
|
||||||
def decommission(site_name, token):
|
def decommission(site_name, token):
|
||||||
"""Remove manifests from apps repo."""
|
"""Remove manifests from apps repo."""
|
||||||
user = env("CI_BOT_USER", "ci-bot")
|
user = env("CI_BOT_USER", "ci-bot")
|
||||||
@@ -249,7 +166,4 @@ def cmd_deploy():
|
|||||||
decommission(site_name, token)
|
decommission(site_name, token)
|
||||||
return
|
return
|
||||||
|
|
||||||
if cfg["type"] == "docker":
|
deploy_static(site_name, site_dir, action_dir, token, cfg)
|
||||||
deploy_docker(site_name, site_dir, action_dir, token, cfg)
|
|
||||||
else:
|
|
||||||
deploy_static(site_name, site_dir, action_dir, token, cfg)
|
|
||||||
|
|||||||
@@ -24,13 +24,6 @@ def ensure_aws():
|
|||||||
subprocess.run(["aws", "--version"], check=True)
|
subprocess.run(["aws", "--version"], check=True)
|
||||||
|
|
||||||
|
|
||||||
def ensure_docker():
|
|
||||||
if shutil.which("docker"):
|
|
||||||
subprocess.run(["docker", "version", "--format", "{{.Client.Version}}"], check=True)
|
|
||||||
return
|
|
||||||
print("WARNING: docker CLI not found — docker builds will fail", file=sys.stderr)
|
|
||||||
|
|
||||||
|
|
||||||
def ensure_jinja2():
|
def ensure_jinja2():
|
||||||
try:
|
try:
|
||||||
import jinja2
|
import jinja2
|
||||||
@@ -45,5 +38,4 @@ def ensure_jinja2():
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
ensure_jinja2()
|
ensure_jinja2()
|
||||||
ensure_aws()
|
ensure_aws()
|
||||||
ensure_docker()
|
|
||||||
print("Setup complete")
|
print("Setup complete")
|
||||||
|
|||||||
+31
-27
@@ -1,4 +1,4 @@
|
|||||||
"""Shared utilities for the publish-site action."""
|
"""Shared utilities for the site-publish action."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
@@ -20,7 +20,26 @@ EXCLUDE_FILES = {
|
|||||||
"Dockerfile", ".dockerignore", "go.mod", "go.sum",
|
"Dockerfile", ".dockerignore", "go.mod", "go.sum",
|
||||||
}
|
}
|
||||||
|
|
||||||
VALID_TYPES = {"static", "hugo", "mkdocs", "docker"}
|
VALID_TYPES = {"static", "hugo", "mkdocs"}
|
||||||
|
|
||||||
|
DOCKER_DEPRECATION_MSG = """\
|
||||||
|
type: docker is no longer supported by action/site-publish.
|
||||||
|
|
||||||
|
site-publish handles only static-content sites (static, hugo, mkdocs)
|
||||||
|
that ship to Garage S3. For containerized web apps, use the standard
|
||||||
|
image-producer chain:
|
||||||
|
|
||||||
|
- uses: action/image-build@v1 # build + smoke-test
|
||||||
|
- uses: action/image-push@v1 # push + prune
|
||||||
|
- uses: action/image-deploy@v1 # apps repo image-pin
|
||||||
|
|
||||||
|
Hand-author your apps-repo manifests once (Deployment, Service, Ingress,
|
||||||
|
Certificate, kustomization with images: block) under
|
||||||
|
sjc001/websites/<repo>/manifests/. image-deploy will pin the tag on
|
||||||
|
every CI run. See action/image-deploy README and
|
||||||
|
sjc001/websites/rainsounds.vino.network/manifests/ for the canonical
|
||||||
|
example.\
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def k8s_name(name):
|
def k8s_name(name):
|
||||||
@@ -57,6 +76,10 @@ def parse_site_yaml(site_dir):
|
|||||||
die("domain is required in site.yaml")
|
die("domain is required in site.yaml")
|
||||||
|
|
||||||
site_type = cfg.get("type", "static")
|
site_type = cfg.get("type", "static")
|
||||||
|
|
||||||
|
if site_type == "docker":
|
||||||
|
die(DOCKER_DEPRECATION_MSG)
|
||||||
|
|
||||||
if site_type not in VALID_TYPES:
|
if site_type not in VALID_TYPES:
|
||||||
die(f"Unknown site type: {site_type} (valid: {', '.join(sorted(VALID_TYPES))})")
|
die(f"Unknown site type: {site_type} (valid: {', '.join(sorted(VALID_TYPES))})")
|
||||||
|
|
||||||
@@ -65,20 +88,10 @@ def parse_site_yaml(site_dir):
|
|||||||
"type": site_type,
|
"type": site_type,
|
||||||
"enabled": cfg.get("enabled", True),
|
"enabled": cfg.get("enabled", True),
|
||||||
"aliases": cfg.get("aliases") or [],
|
"aliases": cfg.get("aliases") or [],
|
||||||
|
"content_dir": cfg.get("content_dir", ""),
|
||||||
|
"tidy": cfg.get("tidy", True),
|
||||||
}
|
}
|
||||||
|
|
||||||
if site_type == "docker":
|
|
||||||
if not cfg.get("image"):
|
|
||||||
die("image is required in site.yaml for type: docker")
|
|
||||||
site["image"] = cfg["image"]
|
|
||||||
site["port"] = cfg.get("port", 8080)
|
|
||||||
site["build_args"] = cfg.get("build_args") or {}
|
|
||||||
site["health_path"] = cfg.get("health_path", "/healthz")
|
|
||||||
site["replicas"] = cfg.get("replicas", 1)
|
|
||||||
else:
|
|
||||||
site["content_dir"] = cfg.get("content_dir", "")
|
|
||||||
site["tidy"] = cfg.get("tidy", True)
|
|
||||||
|
|
||||||
print("Site config:")
|
print("Site config:")
|
||||||
for k, v in site.items():
|
for k, v in site.items():
|
||||||
print(f" {k}: {v}")
|
print(f" {k}: {v}")
|
||||||
@@ -96,30 +109,21 @@ def clone_apps(token):
|
|||||||
return apps_dir
|
return apps_dir
|
||||||
|
|
||||||
|
|
||||||
def render_templates(action_dir, template_vars, app_dir, manifests_dir, site_type):
|
def render_templates(action_dir, template_vars, app_dir, manifests_dir):
|
||||||
"""Render Jinja2 templates, selecting the right set for the site type."""
|
"""Render Jinja2 templates for a static-content site."""
|
||||||
templates_dir = Path(action_dir) / "templates"
|
templates_dir = Path(action_dir) / "templates"
|
||||||
jinja_env = Environment(
|
jinja_env = Environment(
|
||||||
loader=FileSystemLoader(str(templates_dir)),
|
loader=FileSystemLoader(str(templates_dir)),
|
||||||
keep_trailing_newline=True,
|
keep_trailing_newline=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
if site_type == "docker":
|
tmpl_names = ["app.yaml.j2", "certificate.yaml.j2", "ingress.yaml.j2",
|
||||||
service_tmpl = "service-docker.yaml.j2"
|
"kustomization.yaml.j2", "service.yaml.j2"]
|
||||||
tmpl_names = ["app.yaml.j2", "certificate.yaml.j2", "ingress.yaml.j2",
|
|
||||||
"kustomization.yaml.j2", service_tmpl, "deployment.yaml.j2"]
|
|
||||||
else:
|
|
||||||
service_tmpl = "service-static.yaml.j2"
|
|
||||||
tmpl_names = ["app.yaml.j2", "certificate.yaml.j2", "ingress.yaml.j2",
|
|
||||||
"kustomization.yaml.j2", service_tmpl]
|
|
||||||
|
|
||||||
for tmpl_name in tmpl_names:
|
for tmpl_name in tmpl_names:
|
||||||
tmpl = jinja_env.get_template(tmpl_name)
|
tmpl = jinja_env.get_template(tmpl_name)
|
||||||
rendered = tmpl.render(**template_vars)
|
rendered = tmpl.render(**template_vars)
|
||||||
out_name = tmpl_name.replace(".j2", "")
|
out_name = tmpl_name.replace(".j2", "")
|
||||||
# service-docker.yaml / service-static.yaml → service.yaml
|
|
||||||
if out_name.startswith("service-"):
|
|
||||||
out_name = "service.yaml"
|
|
||||||
dest = app_dir / out_name if tmpl_name == "app.yaml.j2" else manifests_dir / out_name
|
dest = app_dir / out_name if tmpl_name == "app.yaml.j2" else manifests_dir / out_name
|
||||||
dest.write_text(rendered)
|
dest.write_text(rendered)
|
||||||
print(f" Rendered {tmpl_name} -> {dest}")
|
print(f" Rendered {tmpl_name} -> {dest}")
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ site_k8s }}
|
|
||||||
namespace: {{ namespace }}
|
|
||||||
labels:
|
|
||||||
app: {{ site_k8s }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ replicas }}
|
|
||||||
strategy:
|
|
||||||
type: Recreate
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: {{ site_k8s }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: {{ site_k8s }}
|
|
||||||
spec:
|
|
||||||
securityContext:
|
|
||||||
runAsNonRoot: true
|
|
||||||
runAsUser: 65532
|
|
||||||
runAsGroup: 65532
|
|
||||||
fsGroup: 65532
|
|
||||||
seccompProfile:
|
|
||||||
type: RuntimeDefault
|
|
||||||
containers:
|
|
||||||
- name: {{ site_k8s }}
|
|
||||||
image: {{ image }}:latest
|
|
||||||
imagePullPolicy: IfNotPresent
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ port }}
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: 64Mi
|
|
||||||
cpu: 50m
|
|
||||||
limits:
|
|
||||||
memory: 256Mi
|
|
||||||
livenessProbe:
|
|
||||||
httpGet: {path: {{ health_path }}, port: http}
|
|
||||||
periodSeconds: 30
|
|
||||||
timeoutSeconds: 3
|
|
||||||
readinessProbe:
|
|
||||||
httpGet: {path: {{ health_path }}, port: http}
|
|
||||||
periodSeconds: 10
|
|
||||||
timeoutSeconds: 3
|
|
||||||
securityContext:
|
|
||||||
allowPrivilegeEscalation: false
|
|
||||||
readOnlyRootFilesystem: true
|
|
||||||
capabilities:
|
|
||||||
drop: ["ALL"]
|
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
kind: Kustomization
|
kind: Kustomization
|
||||||
resources:
|
resources:
|
||||||
{% if site_type == "docker" %}
|
|
||||||
- deployment.yaml
|
|
||||||
{% endif %}
|
|
||||||
- service.yaml
|
- service.yaml
|
||||||
- ingress.yaml
|
- ingress.yaml
|
||||||
- certificate.yaml
|
- certificate.yaml
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ site_k8s }}
|
|
||||||
namespace: {{ namespace }}
|
|
||||||
spec:
|
|
||||||
clusterIP: None
|
|
||||||
selector:
|
|
||||||
app: {{ site_k8s }}
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
port: 80
|
|
||||||
targetPort: http
|
|
||||||
Reference in New Issue
Block a user