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
46 changes: 8 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,44 +13,14 @@ standards, reproducible quality tooling, and selectable source-control hosting.

## Start an Independent Project

Prefer GitHub's **Use this template** action. It creates a repository with an
independent initial commit instead of inheriting the boilerplate history. Fork
only when contributing changes back to this boilerplate.

After creating the repository, preview the one-time setup command. Choose the
hosting provider and collaboration model independently:

| Host | Collaboration | Result |
| :--- | :--- | :--- |
| `github` | `collaborative` | GitHub automation and public collaboration baseline |
| `github` | `solo` | GitHub automation without public collaboration files |
| `gitlab` | `collaborative` | GitLab automation and team collaboration baseline |
| `gitlab` | `solo` | GitLab automation without public collaboration files |
| `neutral` | `collaborative` | Provider-neutral team documentation and local tooling |
| `neutral` | `solo` | Minimal provider-neutral project and local tooling |

Example preview:

```bash
uv run python scripts/setup_project.py \
--host github \
--collaboration collaborative \
--distribution-name example-service \
--import-package example_service \
--display-name "Example Service" \
--description "Describe the project's value." \
--author-name "Your Name" \
--author-email "you@example.com" \
--project-license mit \
--repository-url https://github.com/example/example-service \
--code-owner @example
```

Review the plan, then repeat it with `--apply`. See
[Getting Started](docs/getting-started.md) and the complete
[customization guide](docs/project/customization.md) before applying it.
Apply mode requires a clean Git worktree with the boilerplate baseline
committed and stages all transformations before publishing them.
Create an independent repository rather than a fork unless you intend to
contribute changes back to this boilerplate. Then follow the single linear
[Getting Started guide](docs/getting-started.md) from repository creation
through project setup and verification.

The [customization reference](docs/project/customization.md) explains the
available setup fields and generated behavior. Consult it when choosing values;
the executable sequence remains in Getting Started.

## What the Baseline Provides

Expand Down
8 changes: 4 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Documentation

- [Getting Started](getting-started.md) explains repository creation, local
setup, and the first verification.
- [Customizing the Boilerplate](project/customization.md) documents every
automated and manual conversion step.
- [Getting Started](getting-started.md) is the ordered walkthrough for
repository creation, local setup, and the first verification.
- [Customizing the Boilerplate](project/customization.md) is the reference for
setup fields, choices, and generated behavior.
- [Development Tooling](development-tooling.md) explains local and hosted
quality gates.
- [Agent Configuration](project/agent-configuration.md) describes Codex
Expand Down
91 changes: 79 additions & 12 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,16 @@ the boilerplate repository's `.git` directory.
Create the repository using the host's template or repository-copy mechanism.
Select `neutral` during setup so GitHub and GitLab files are removed.

## Create the Environment
## Create the Initial Environment

```bash
uv sync --locked
```

This environment initially carries the boilerplate prompt. Project setup
cannot safely replace an environment while its Python process is running, so a
later step recreates it with the new distribution name.

## Preview Project Setup

The setup command combines two independent choices:
Expand All @@ -59,8 +63,31 @@ The setup command combines two independent choices:
- `--collaboration solo|collaborative` selects contribution infrastructure.

It also requires explicit project identity, authorship, and license treatment.
Run the example in the root README without `--apply`, inspect every reported
action, and then apply the same command explicitly.
The author fields populate Python package metadata and generated project
documents; they do not configure Git identity.

Preview setup first. This GitLab solo example intentionally omits
`--repository-url`; repository links may be added to the resulting project
metadata after the remote repository exists:

```bash
uv run python scripts/setup_project.py \
--host gitlab \
--collaboration solo \
--distribution-name example-service \
--import-package example_service \
--display-name "Example Service" \
--description "Processes example events." \
--author-name "Example Team" \
--author-email "team@example.com" \
--project-license mit
```

Inspect every reported action, then repeat the same command with `--apply`.
Collaborative GitHub and GitLab projects additionally require
`--repository-url` and `--code-owner`. A repository URL only populates package
metadata and generated links; setup never creates a remote repository or
changes a Git remote.

`--project-license mit` keeps the root MIT license as the new project's
license. `--project-license unset` removes the project-level license metadata
Expand All @@ -71,20 +98,60 @@ The command customizes project files, regenerates `uv.lock`, and removes its
one-time templates and tests. It never commits, rewrites history, changes a
remote, or pushes.

## Complete the Manual Steps
## Recreate the Project Environment

If the initial environment is active, deactivate it. Then replace it so its
shell prompt uses the new distribution name and synchronize the dependencies:

```bash
deactivate
uv venv --clear --prompt "example-service"
uv sync --locked
```

Omit `deactivate` when no virtual environment is active. `--clear` replaces
the existing `.venv`; do not use it for an environment containing unrecorded
manual changes.

## Configure Git Identity and Signing

Set repository-local identity when it should differ from the global Git
configuration:

```bash
git config --local user.name "Your Name"
git config --local user.email "you@example.com"
```

For GPG signing, list available secret keys, copy the long key ID from the
`sec` entry, and configure signing for this repository:

```bash
gpg --list-secret-keys --keyid-format=long
git config --local user.signingkey YOUR_KEY_ID
git config --local commit.gpgsign true
git config --local tag.gpgsign true
```

Verify the effective local configuration without exposing private key
material:

```bash
git config --local --list
```

## Complete Setup and Verify

After setup:

1. complete `docs/project/definition.md`;
2. decide only technical questions required for the first useful milestone;
3. configure repository-local Git identity and signing when required;
4. apply the selected host's documented remote settings;
5. add only required CI secrets and integrations;
6. install local hooks; and
7. run the complete verification.
3. apply the selected host's documented remote settings;
4. add only required CI secrets and integrations;
5. install local hooks; and
6. run the complete verification.

```bash
git config --local --list
git remote -v
uv run pre-commit install --hook-type pre-commit --hook-type pre-push
uv lock --check
Expand All @@ -93,5 +160,5 @@ uv run pre-commit run --all-files --hook-stage pre-push
uv build
```

For all identity fields, manual decisions, provider behavior, and completion
criteria, follow the [customization guide](project/customization.md).
For the meaning and constraints of individual setup fields, consult the
[customization reference](project/customization.md).
77 changes: 28 additions & 49 deletions docs/project/customization.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Customizing the Boilerplate

Use this checklist once, immediately after creating a repository from the
boilerplate and before implementing product behavior. The setup command
automates deterministic repository transformations; product, legal, security,
and operational decisions remain explicit human work.
Use this reference while following the linear
[Getting Started guide](../getting-started.md). This document explains setup
choices and generated behavior; it intentionally does not duplicate the
executable walkthrough. The setup command automates deterministic repository
transformations, while product, legal, security, and operational decisions
remain explicit human work.

## 1. Choose Repository Creation and Git History

Expand All @@ -17,11 +19,10 @@ Prefer a template mechanism over a fork:
- a normal clone preserves boilerplate history and is acceptable when that
provenance is wanted.

For a fresh GitLab history, use `git archive` to copy the tracked working tree
into a new directory, run `git init -b main` there, and commit that unchanged
baseline before customization. The setup command requires this clean recovery
point. Commit the customized result separately after reviewing it. Do not
delete or rewrite the source repository's history.
For a fresh GitLab history, Getting Started provides the exact export and Git
initialization sequence. Commit the unchanged baseline before customization so
setup has a clean recovery point. Do not delete or rewrite the source
repository's history.

The setup command never deletes `.git`, rewrites commits, changes remotes,
commits, or pushes. Do not rename inherited commits: either keep their history
Expand Down Expand Up @@ -56,13 +57,20 @@ Prepare these values:
| Import package | `example_service` | `src/`, imports, coverage, and Import Linter |
| Display name | `Example Service` | README and package documentation |
| Description | `Processes example events.` | Package and repository metadata |
| Author | `Example Team` | Package ownership metadata |
| Author email | `team@example.com` | Package ownership metadata |
| Author | `Example Team` | Package metadata and generated documents |
| Author email | `team@example.com` | Package metadata and generated documents |
| Repository URL | `https://host/group/example-service` | Hosted project links |
| Code Owner | `@example-team` | Collaborative host ownership |

Hosted profiles require a repository URL. Hosted collaborative profiles also
require a Code Owner. Neutral profiles reject those provider-specific values.
Hosted solo profiles accept an optional repository URL, allowing setup before
the remote repository exists. Hosted collaborative profiles require both a
repository URL and a Code Owner. Neutral profiles reject those
provider-specific values.

The repository URL only populates package metadata and links in generated
files. It does not create a repository, configure a remote, or contact the
hosting provider. Author fields likewise do not configure Git identity; follow
Getting Started for repository-local identity and signing commands.

## 4. Decide License Treatment

Expand All @@ -76,26 +84,9 @@ Choose explicitly:
The second option does not select a new project license. Apply organizational
or legal policy separately, and never delete the inherited third-party notice.

## 5. Preview and Apply

Preview first:

```bash
uv run python scripts/setup_project.py \
--host gitlab \
--collaboration collaborative \
--distribution-name example-service \
--import-package example_service \
--display-name "Example Service" \
--description "Processes example events." \
--author-name "Example Team" \
--author-email "team@example.com" \
--project-license unset \
--repository-url https://gitlab.example.com/group/example-service \
--code-owner @example-team
```
## 5. Setup Behavior

Inspect the plan and repeat it with `--apply`. The command:
Getting Started owns the preview-and-apply command sequence. The command:

- validates that it is running against a fresh boilerplate;
- selects one host and one collaboration profile;
Expand Down Expand Up @@ -133,15 +124,9 @@ because they are not project decision history.

## 7. Configure Git and the Hosting Platform

Inspect local configuration and remotes:

```bash
git config --local --list
git remote -v
```

Set repository-local identity or signing only when it should differ from the
user's global configuration. Never copy another project's signing key.
Getting Started owns the commands for repository-local identity, GPG signing,
and remote inspection. Author metadata supplied to setup is independent from
Git configuration. Never copy another project's signing key.

For GitHub, apply `.github/REPOSITORY_SETTINGS.md`. For GitLab, apply
`.gitlab/REPOSITORY_SETTINGS.md`. These blueprints cover protected branches,
Expand All @@ -167,14 +152,8 @@ Do not add dependencies or infrastructure merely because they are common.

## 9. Verify the Result

```bash
uv lock --check
uv run pre-commit run --all-files
uv run pre-commit run --all-files --hook-stage pre-push
uv build
```

Then verify manually:
Run the complete quality-gate sequence in Getting Started, then verify
manually:

- no boilerplate identity remains in project-owned metadata;
- exactly one provider baseline is present, or none for `neutral`;
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "codex-python-boilerplate"
version = "1.0.0"
version = "1.0.1"
description = "An opinionated Codex-native foundation for Python projects"
authors = [{ name = "Emad Helmi", email = "s.emad.helmi@gmail.com" }]
readme = "README.md"
Expand Down
20 changes: 18 additions & 2 deletions scripts/setup_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,13 @@ def validate_config(config: SetupConfig) -> None:
"Neutral projects cannot use provider-specific repository "
"or Code Owner values."
)
elif config.repository_url is None:
elif (
config.collaboration == "collaborative"
and config.repository_url is None
):
raise ProjectSetupError(
"GitHub and GitLab projects require --repository-url."
"Collaborative GitHub and GitLab projects require "
"--repository-url."
)
elif config.repository_url is not None:
_validate_repository_url(config.host, config.repository_url)
Expand Down Expand Up @@ -950,6 +954,18 @@ def main(argv: list[str] | None = None) -> int:
print(f"- {action}")
if not arguments.apply:
print("Re-run with --apply to perform these changes.")
else:
print("Next steps:")
print("- deactivate the current virtual environment if it is active")
print(
"- the next command replaces .venv; preserve any unrecorded "
"manual changes first"
)
print(
"- recreate the local environment with the project prompt: "
f'uv venv --clear --prompt "{config.distribution_name}"'
)
print("- synchronize it: uv sync --locked")
return 0


Expand Down
Loading
Loading