Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions .github/scripts/rename-template.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
#!/usr/bin/env python3
"""Rename template placeholders when a new repo is created from the template."""

import os
import re


def to_kebab(name: str) -> str:
return name.lower().replace("_", "-")


def to_snake(name: str) -> str:
return name.lower().replace("-", "_")


def to_title(name: str) -> str:
return " ".join(word.capitalize() for word in re.split(r"[-_]", name))


def to_pascal(name: str) -> str:
return "".join(word.capitalize() for word in re.split(r"[-_]", name))


def sanitize_docker(name: str) -> str:
if name[0].isdigit():
name = "app-" + name
return re.sub(r"[^a-z0-9-]", "-", name)


def main():
repo_full = os.environ.get("GITHUB_REPOSITORY", "")
if not repo_full:
raise RuntimeError("GITHUB_REPOSITORY not set")

repo_name = repo_full.split("/")[-1]
kebab = sanitize_docker(to_kebab(repo_name))
snake = to_snake(repo_name)
title = to_title(repo_name)
pascal = to_pascal(repo_name)

replacements = [
(
"compose.yaml",
[
(r"^ frankenphp:\n", f" {kebab}:\n"),
(r"^ container_name: frankenphp\n", f" container_name: {kebab}\n"),
],
),
(
".devcontainer/devcontainer.json",
[
('"name": "PHP Starter Kit"', f'"name": "{title}"'),
('"service": "frankenphp"', f'"service": "{kebab}"'),
],
),
(
"makefile",
[
(r"exec --user=robbyte frankenphp", f"exec --user=robbyte {kebab}"),
(r"exec frankenphp cat", f"exec {kebab} cat"),
],
),
(
"build/prod/docker-entrypoint.sh",
[
('echo "PHP Starter Kit - Starting..."', f'echo "{title} - Starting..."'),
],
),
(
"src/public/index.php",
[
("<title>PHP Starter Kit — Setup Wizard</title>", f"<title>{title} — Setup Wizard</title>"),
('<div class="hero-badge">PHP Starter Kit</div>', f'<div class="hero-badge">{title}</div>'),
("PHP Starter Kit &copy;", f"{title} &copy;"),
],
),
(
"README.md",
[
("# PHP Starter Kit", f"# {title}"),
("https://github.com/rdurica/php_starter_kit.git", f"https://github.com/{repo_full}.git"),
("https://github.com/rdurica/php_starter_kit/actions", f"https://github.com/{repo_full}/actions"),
("cd php_starter_kit", f"cd {repo_name}"),
],
),
(
"AGENTS.md",
[
("# Agent Context for PHP Starter Kit", f"# Agent Context for {title}"),
("docker compose exec frankenphp", f"docker compose exec {kebab}"),
],
),
]

for filepath, rules in replacements:
if not os.path.exists(filepath):
print(f"Warning: {filepath} not found, skipping")
continue

with open(filepath, "r", encoding="utf-8") as f:
content = f.read()

original = content
for pattern, replacement in rules:
flags = re.MULTILINE if pattern.startswith("^") else 0
content = re.sub(pattern, replacement, content, flags=flags)

if content != original:
with open(filepath, "w", encoding="utf-8") as f:
f.write(content)
print(f"Updated: {filepath}")
else:
print(f"No changes: {filepath}")

with open(".template-configured", "w", encoding="utf-8") as f:
f.write(f"Configured from template for {repo_full}\n")
print("Created: .template-configured")


if __name__ == "__main__":
main()
3 changes: 0 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ jobs:
- name: Validate CI Compose config
run: docker compose -f compose.ci.yaml config

- name: Validate demo Compose config
run: docker compose -f compose.demo.yaml config

tests:
name: Framework Tests
runs-on: ubuntu-latest
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ jobs:
- name: Validate CI Compose config
run: docker compose -f compose.ci.yaml config

- name: Validate demo Compose config
run: docker compose -f compose.demo.yaml config

frontend:
name: Frontend Quality
runs-on: ubuntu-latest
Expand Down
51 changes: 51 additions & 0 deletions .github/workflows/template-setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Template Setup

on:
push:
branches:
- main

permissions:
contents: write

jobs:
rename:
name: Rename from template
runs-on: ubuntu-latest
if: github.repository != 'rdurica/php_starter_kit'

steps:
- name: Checkout
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Check if already configured
id: check
run: |
if [ -f ".template-configured" ]; then
echo "already_configured=true" >> "$GITHUB_OUTPUT"
else
echo "already_configured=false" >> "$GITHUB_OUTPUT"
fi

- name: Run rename script
if: steps.check.outputs.already_configured == 'false'
run: python3 .github/scripts/rename-template.py

- name: Commit and push renamed files
if: steps.check.outputs.already_configured == 'false'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "chore: rename project from template [skip ci]"
git push

- name: Remove template setup files
if: steps.check.outputs.already_configured == 'false'
run: |
git rm .github/workflows/template-setup.yml
git rm -rf .github/scripts
git commit -m "chore: remove template setup workflow [skip ci]"
git push
13 changes: 1 addition & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ This starter kit provides a ready-to-use, out-of-the-box local development envir

- **FrankenPHP** — Modern PHP application server with HTTP/2, HTTP/3, and automatic HTTPS
- **Secure by default** — Non-root user, security headers, hardened sessions, no `expose_php`
- **Multi-environment** — Dev, CI, and Demo configurations
- **Multi-environment** — Dev and CI configurations
- **Multi-stage production build** — Minimal attack surface, optimized layers
- **CI/CD ready** — GitHub Actions with code quality, tests, security scanning
- **DevContainer support** — VSCode remote containers out of the box
Expand Down Expand Up @@ -109,11 +109,6 @@ After installation, you can delete `/setup.php` via the success dialog or manual
- SQLite in-memory for fast tests
- Ideal for GitHub Actions

### Demo (`compose.demo.yaml`)
- Self-contained stack with PostgreSQL and Redis
- Uses prebuilt GHCR image
- Port 8080 on host

## Production

Build the production image:
Expand All @@ -122,12 +117,6 @@ Build the production image:
docker build -f build/prod/Dockerfile -t myapp:latest .
```

Run with the demo stack:

```bash
docker compose -f compose.demo.yaml up
```

## CI/CD

Three GitHub Actions workflows are included:
Expand Down
39 changes: 0 additions & 39 deletions compose.demo.yaml

This file was deleted.

40 changes: 0 additions & 40 deletions demo.env

This file was deleted.

Loading