From 4bac2a1f0b0ce62a13aa1bcfb13b33c8d1b73b34 Mon Sep 17 00:00:00 2001 From: Jiri Uhlir Date: Wed, 3 Jun 2026 09:36:00 +0200 Subject: [PATCH] Add service template generators --- scripts/new-dotnet-api-app.sh | 116 ++++++++++++++++++++++++++ scripts/new-dotnet-worker-app.sh | 102 +++++++++++++++++++++++ scripts/new-nodejs-ts-app.sh | 137 +++++++++++++++++++++++++++++++ scripts/new-static-site-app.sh | 92 +++++++++++++++++++++ 4 files changed, 447 insertions(+) create mode 100755 scripts/new-dotnet-api-app.sh create mode 100755 scripts/new-dotnet-worker-app.sh create mode 100755 scripts/new-nodejs-ts-app.sh create mode 100755 scripts/new-static-site-app.sh diff --git a/scripts/new-dotnet-api-app.sh b/scripts/new-dotnet-api-app.sh new file mode 100755 index 0000000..0601a06 --- /dev/null +++ b/scripts/new-dotnet-api-app.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash +set -euo pipefail + +source /opt/appfactory/config/appfactory.env + +APP_ID="${1:-}" +APP_NAME="${2:-$APP_ID}" + +if [ -z "$APP_ID" ]; then + echo "Usage: new-dotnet-api-app.sh [app-name]" + exit 1 +fi + +APP_DIR="$WORKSPACE_DIR/$APP_ID" +PROJECT_NAME="$(python3 - "$APP_ID" <<'PY' +import re, sys +parts = re.split(r'[^a-zA-Z0-9]+', sys.argv[1]) +print(''.join(p[:1].upper() + p[1:] for p in parts if p)) +PY +)" + +mkdir -p "$APP_DIR" +cd "$APP_DIR" + +cat > "$PROJECT_NAME.csproj" < + + net8.0 + enable + enable + + +EOF_DOTNET + +cat > Program.cs < Results.Json(new +{ + name = "$APP_NAME", + service = "$APP_ID", + status = "ok" +})); + +app.MapGet("/health", () => Results.Json(new +{ + status = "ok" +})); + +app.Run(); +EOF_DOTNET + +cat > appsettings.json <<'EOF_JSON' +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} +EOF_JSON + +cat > Dockerfile < .dockerignore <<'EOF_IGNORE' +bin/ +obj/ +.git/ +EOF_IGNORE + +cat > README.md </dev/null || true + +GITEA_PUSH_URL="${GITEA_URL/http:\/\//http:\/\/${GITEA_TOKEN}@}" +git remote remove origin 2>/dev/null || true +git remote add origin "$GITEA_PUSH_URL/$GITEA_ORG/$APP_ID.git" +git push -u origin main diff --git a/scripts/new-dotnet-worker-app.sh b/scripts/new-dotnet-worker-app.sh new file mode 100755 index 0000000..04ad247 --- /dev/null +++ b/scripts/new-dotnet-worker-app.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +set -euo pipefail + +source /opt/appfactory/config/appfactory.env + +APP_ID="${1:-}" +APP_NAME="${2:-$APP_ID}" + +if [ -z "$APP_ID" ]; then + echo "Usage: new-dotnet-worker-app.sh [app-name]" + exit 1 +fi + +APP_DIR="$WORKSPACE_DIR/$APP_ID" +PROJECT_NAME="$(python3 - "$APP_ID" <<'PY' +import re, sys +parts = re.split(r'[^a-zA-Z0-9]+', sys.argv[1]) +print(''.join(p[:1].upper() + p[1:] for p in parts if p)) +PY +)" + +mkdir -p "$APP_DIR" +cd "$APP_DIR" + +cat > "$PROJECT_NAME.csproj" < + + net8.0 + enable + enable + + +EOF_DOTNET + +cat > Program.cs <(); + +var host = builder.Build(); +host.Run(); + +public class Worker : BackgroundService +{ + private readonly ILogger _logger; + + public Worker(ILogger logger) + { + _logger = logger; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + _logger.LogInformation("Service $APP_ID is running at {time}", DateTimeOffset.Now); + await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken); + } + } +} +EOF_DOTNET + +cat > Dockerfile < .dockerignore <<'EOF_IGNORE' +bin/ +obj/ +.git/ +EOF_IGNORE + +cat > README.md </dev/null || true + +GITEA_PUSH_URL="${GITEA_URL/http:\/\//http:\/\/${GITEA_TOKEN}@}" +git remote remove origin 2>/dev/null || true +git remote add origin "$GITEA_PUSH_URL/$GITEA_ORG/$APP_ID.git" +git push -u origin main diff --git a/scripts/new-nodejs-ts-app.sh b/scripts/new-nodejs-ts-app.sh new file mode 100755 index 0000000..b362677 --- /dev/null +++ b/scripts/new-nodejs-ts-app.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env bash +set -euo pipefail + +source /opt/appfactory/config/appfactory.env + +APP_ID="${1:-}" +APP_NAME="${2:-$APP_ID}" + +if [ -z "$APP_ID" ]; then + echo "Usage: new-nodejs-ts-app.sh [app-name]" + exit 1 +fi + +APP_DIR="$WORKSPACE_DIR/$APP_ID" + +mkdir -p "$APP_DIR/src" +cd "$APP_DIR" + +cat > package.json < tsconfig.json <<'EOF_JSON' +{ + "compilerOptions": { + "target": "ES2022", + "module": "CommonJS", + "outDir": "dist", + "rootDir": "src", + "strict": true, + "esModuleInterop": true + } +} +EOF_JSON + +cat > src/index.ts < { + res.json({ + name: "$APP_NAME", + service: "$APP_ID", + status: "ok" + }); +}); + +app.get("/health", (_req, res) => { + res.json({ status: "ok" }); +}); + +if (rootPath) { + app.get(rootPath, (_req, res) => { + res.json({ + name: "$APP_NAME", + service: "$APP_ID", + status: "ok" + }); + }); + + app.get(rootPath + "/health", (_req, res) => { + res.json({ status: "ok" }); + }); +} + +app.listen(port, "0.0.0.0", () => { + console.log("$APP_ID listening on port " + port); +}); +EOF_TS + +cat > Dockerfile <<'EOF_DOCKER' +FROM node:20-slim AS build +WORKDIR /app +COPY package*.json ./ +RUN npm install +COPY . . +RUN npm run build + +FROM node:20-slim +WORKDIR /app +ENV PORT=3000 +EXPOSE 3000 +COPY package*.json ./ +RUN npm install --omit=dev +COPY --from=build /app/dist ./dist +CMD ["npm", "start"] +EOF_DOCKER + +cat > .dockerignore <<'EOF_IGNORE' +node_modules/ +dist/ +.git/ +EOF_IGNORE + +cat > README.md </dev/null || true + +GITEA_PUSH_URL="${GITEA_URL/http:\/\//http:\/\/${GITEA_TOKEN}@}" +git remote remove origin 2>/dev/null || true +git remote add origin "$GITEA_PUSH_URL/$GITEA_ORG/$APP_ID.git" +git push -u origin main diff --git a/scripts/new-static-site-app.sh b/scripts/new-static-site-app.sh new file mode 100755 index 0000000..cc076b1 --- /dev/null +++ b/scripts/new-static-site-app.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +set -euo pipefail + +source /opt/appfactory/config/appfactory.env + +APP_ID="${1:-}" +APP_NAME="${2:-$APP_ID}" + +if [ -z "$APP_ID" ]; then + echo "Usage: new-static-site-app.sh [app-name]" + exit 1 +fi + +APP_DIR="$WORKSPACE_DIR/$APP_ID" + +mkdir -p "$APP_DIR" +cd "$APP_DIR" + +cat > index.html < + + + + $APP_NAME + + + +
+

$APP_NAME

+

Služba $APP_ID běží.

+
+ + +EOF_HTML + +cat > health.json <<'EOF_JSON' +{ + "status": "ok" +} +EOF_JSON + +cat > nginx.conf <<'EOF_CONF' +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /health { + default_type application/json; + alias /usr/share/nginx/html/health.json; + } +} +EOF_CONF + +cat > Dockerfile <<'EOF_DOCKER' +FROM nginx:1.27-alpine +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY index.html /usr/share/nginx/html/index.html +COPY health.json /usr/share/nginx/html/health.json +EXPOSE 80 +EOF_DOCKER + +cat > .dockerignore <<'EOF_IGNORE' +.git/ +EOF_IGNORE + +cat > README.md </dev/null || true + +GITEA_PUSH_URL="${GITEA_URL/http:\/\//http:\/\/${GITEA_TOKEN}@}" +git remote remove origin 2>/dev/null || true +git remote add origin "$GITEA_PUSH_URL/$GITEA_ORG/$APP_ID.git" +git push -u origin main