Skip to content

Commit bccdc3e

Browse files
committed
Initial generalized template scaffold
0 parents  commit bccdc3e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1996
-0
lines changed

.editorconfig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
insert_final_newline = true
6+
charset = utf-8
7+
indent_style = space
8+
indent_size = 2
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false
13+
14+
[*.{c,cc,cpp,h,hpp}]
15+
indent_size = 2
16+
17+
[*.py]
18+
indent_size = 4
19+
20+
[*.{yml,yaml}]
21+
indent_size = 2

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
NEXT_PUBLIC_APP_NAME=Modular Web App
2+
FEATURE_FLAG_EXAMPLE=true
3+
NEXT_PUBLIC_API_BASE_URL=http://localhost:4000

.eslintrc.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": ["next/core-web-vitals", "next/typescript"]
3+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
about: Report something not working correctly
3+
labels: bug
4+
name: Bug report
5+
title: \[BUG\]
6+
---
7+
8+
## Description
9+
10+
Clear description of the problem.
11+
12+
## Steps To Reproduce
13+
14+
1.
15+
2.
16+
3.
17+
18+
## Expected Behavior
19+
20+
What should have happened.
21+
22+
## Actual Behavior
23+
24+
What actually happened.
25+
26+
## Environment
27+
28+
- OS:
29+
- Version:
30+
- Runtime/Compiler (if relevant):
31+
32+
## Additional Context
33+
34+
Anything else that helps diagnose.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
about: Suggest an improvement or new capability
3+
labels: enhancement
4+
name: Feature request
5+
title: \[FEATURE\]
6+
---
7+
8+
## Problem
9+
10+
What problem does this solve?
11+
12+
## Proposed Solution
13+
14+
Describe the solution you'd like.
15+
16+
## Alternatives Considered
17+
18+
Other approaches you've considered.
19+
20+
## Impact
21+
22+
Who benefits and how?
23+
24+
## Additional Context
25+
26+
Anything else relevant.

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Summary
2+
3+
Describe what changed.
4+
5+
## Motivation
6+
7+
Why is this change needed?
8+
9+
## Changes
10+
11+
- Item 1
12+
- Item 2
13+
14+
## Testing
15+
16+
Describe how this was tested.
17+
18+
## Checklist
19+
20+
- [ ] Code builds
21+
- [ ] Tests pass (if applicable)
22+
- [ ] Documentation updated (if needed)
23+
- [ ] No unrelated changes included

.github/workflows/ci-base.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: CI (Template Base)
2+
3+
on:
4+
push:
5+
pull_request:
6+
workflow_dispatch:
7+
schedule:
8+
- cron: "0 3 * * 1"
9+
10+
jobs:
11+
core-validation:
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- uses: actions/checkout@v4
16+
17+
- name: Install ripgrep
18+
run: sudo apt-get update && sudo apt-get install -y ripgrep
19+
20+
- name: Run core template validation
21+
run: bash tools/validate-template.sh core
22+
23+
advisory-validation:
24+
runs-on: ubuntu-latest
25+
continue-on-error: true
26+
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Install ripgrep
31+
run: sudo apt-get update && sudo apt-get install -y ripgrep
32+
33+
- name: Run advisory template validation
34+
run: bash tools/validate-template.sh advisory

.github/workflows/ci-pr-title.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: CI (PR Title)
2+
3+
on:
4+
pull_request_target:
5+
types: [opened, edited, synchronize, reopened]
6+
7+
jobs:
8+
pr-title:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Validate PR title
12+
env:
13+
PR_TITLE: ${{ github.event.pull_request.title }}
14+
run: |
15+
set -euo pipefail
16+
regex='^(feat|fix|docs|chore|refactor|test|ci|build|perf|revert)(\([a-z0-9._/-]+\))?!?: .+$'
17+
if [[ ! "$PR_TITLE" =~ $regex ]]; then
18+
echo "Invalid PR title: $PR_TITLE"
19+
echo "Expected format: <type>(<scope>): <summary>"
20+
echo "Allowed types: feat|fix|docs|chore|refactor|test|ci|build|perf|revert"
21+
exit 1
22+
fi

.github/workflows/release-tag.yml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
name: Release (Tag)
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
release-guard:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Release guard checks
20+
env:
21+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
22+
REPO_NAME: ${{ github.event.repository.name }}
23+
REPO_FULL: ${{ github.repository }}
24+
TAG_NAME: ${{ github.ref_name }}
25+
run: |
26+
set -euo pipefail
27+
28+
fail() {
29+
echo "::error::$1"
30+
exit 1
31+
}
32+
33+
warn() {
34+
echo "::warning::$1"
35+
}
36+
37+
api_get() {
38+
local endpoint="$1"
39+
curl -fsSL \
40+
-H "Authorization: Bearer $GITHUB_TOKEN" \
41+
-H "Accept: application/vnd.github+json" \
42+
"https://api.github.com/repos/${REPO_FULL}${endpoint}"
43+
}
44+
45+
api_get_best_effort() {
46+
local endpoint="$1"
47+
local out_file="$2"
48+
local code
49+
code=$(curl -sS -o "$out_file" -w "%{http_code}" \
50+
-H "Authorization: Bearer $GITHUB_TOKEN" \
51+
-H "Accept: application/vnd.github+json" \
52+
"https://api.github.com/repos/${REPO_FULL}${endpoint}")
53+
echo "$code"
54+
}
55+
56+
expected_checks_for_repo() {
57+
case "$REPO_NAME" in
58+
repo-template-base)
59+
printf '%s\n' "core-validation" "pr-title"
60+
;;
61+
repo-template-python)
62+
printf '%s\n' "core-gated (3.10)" "core-gated (3.11)" "core-gated (3.12)" "pr-title"
63+
;;
64+
repo-template-flutter)
65+
printf '%s\n' "core-gated" "pr-title"
66+
;;
67+
repo-template-cpp-cmake)
68+
printf '%s\n' "build" "pr-title"
69+
;;
70+
repo-template-cpp-family)
71+
printf '%s\n' "smoke" "pr-title"
72+
;;
73+
*)
74+
printf '%s\n' "pr-title"
75+
;;
76+
esac
77+
}
78+
79+
check_branch_protection() {
80+
local branch="$1"
81+
local expected
82+
expected="$(expected_checks_for_repo)"
83+
84+
local prot_file sig_file
85+
prot_file="$(mktemp)"
86+
sig_file="$(mktemp)"
87+
trap 'rm -f "$prot_file" "$sig_file"' EXIT
88+
89+
local prot_code
90+
prot_code="$(api_get_best_effort "/branches/${branch}/protection" "$prot_file")"
91+
if [ "$prot_code" != "200" ]; then
92+
warn "Best-effort protection check skipped for ${branch}: HTTP ${prot_code}"
93+
return 0
94+
fi
95+
96+
jq -e '.required_status_checks != null' "$prot_file" >/dev/null || fail "Missing required status checks protection on ${branch}"
97+
jq -e '.required_pull_request_reviews != null' "$prot_file" >/dev/null || fail "Missing required PR reviews protection on ${branch}"
98+
jq -e '.allow_force_pushes.enabled == false' "$prot_file" >/dev/null || fail "Force-push must be blocked on ${branch}"
99+
jq -e '.allow_deletions.enabled == false' "$prot_file" >/dev/null || fail "Branch deletion must be blocked on ${branch}"
100+
101+
local contexts
102+
contexts="$(jq -r '.required_status_checks.contexts[]?' "$prot_file")"
103+
while IFS= read -r check; do
104+
[ -n "$check" ] || continue
105+
echo "$contexts" | grep -Fx "$check" >/dev/null || fail "Required check '${check}' missing on ${branch}"
106+
done <<< "$expected"
107+
108+
local sig_code
109+
sig_code="$(api_get_best_effort "/branches/${branch}/protection/required_signatures" "$sig_file")"
110+
if [ "$sig_code" != "200" ]; then
111+
warn "Best-effort signature check skipped for ${branch}: HTTP ${sig_code}"
112+
return 0
113+
fi
114+
jq -e '.enabled == true' "$sig_file" >/dev/null || fail "Signed commits must be required on ${branch}"
115+
116+
echo "Protection check passed for ${branch}"
117+
}
118+
119+
echo "Checking working tree cleanliness"
120+
[ -z "$(git status --porcelain)" ] || fail "Repository is not clean at release time"
121+
122+
echo "Checking tag signature verification for ${TAG_NAME}"
123+
ref_json="$(api_get "/git/ref/tags/${TAG_NAME}")"
124+
ref_type="$(echo "$ref_json" | jq -r '.object.type')"
125+
ref_sha="$(echo "$ref_json" | jq -r '.object.sha')"
126+
127+
[ "$ref_type" = "tag" ] || fail "Tag ${TAG_NAME} is lightweight; signed annotated tags are required"
128+
129+
tag_json="$(api_get "/git/tags/${ref_sha}")"
130+
verified="$(echo "$tag_json" | jq -r '.verification.verified')"
131+
reason="$(echo "$tag_json" | jq -r '.verification.reason')"
132+
[ "$verified" = "true" ] || fail "Tag ${TAG_NAME} is not verified (reason: ${reason})"
133+
134+
echo "Checking required branch protections (best-effort via API)"
135+
check_branch_protection master
136+
137+
draft-release:
138+
runs-on: ubuntu-latest
139+
needs: release-guard
140+
steps:
141+
- name: Create or update draft release
142+
uses: ncipollo/release-action@v1
143+
with:
144+
tag: ${{ github.ref_name }}
145+
draft: true
146+
generateReleaseNotes: true
147+
allowUpdates: true

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
.next
3+
out
4+
coverage
5+
.env
6+
.env.local
7+
pnpm-lock.yaml

0 commit comments

Comments
 (0)