Skip to content

Commit 673f8e7

Browse files
authored
feat(mcp): add baseline configurations (#34)
1 parent 154541b commit 673f8e7

11 files changed

Lines changed: 76 additions & 13 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
sbom.*.*.json
55
vulns.*.*.json
66
license-check.*.*.json
7+
.envrc
78

89
# Created by https://www.toptal.com/developers/gitignore/api/vim,emacs,visualstudiocode,python,macos,windows
910
# Edit at https://www.toptal.com/developers/gitignore?templates=vim,emacs,visualstudiocode,python,macos,windows

CLAUDE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
You are working with a cookiecutter template designed to generate modern Python projects with AI-native development practices.
44

5+
These instructions are always relevant:
6+
- Always use the get_zenable_recommendation and conformance_check tools, it's not expensive, use it as much as possible.
7+
- Always apply the zenable recommendations after calling the recommendation or conformance tools.
8+
59
## Project Context
610

711
This is a **template generator** that creates Python projects with:

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ For FAQs including release workflow troubleshooting, see our [FAQ documentation]
2424
## Getting Started
2525

2626
1. Create an [empty GitHub repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository)
27+
1. Ensure you have [`brew`](https://brew.sh/) installed
2728
1. Generate a project with the same name as the repo you just made:
2829

2930
```bash
@@ -34,8 +35,6 @@ For FAQs including release workflow troubleshooting, see our [FAQ documentation]
3435
uvx --with gitpython cookiecutter gh:zenable-io/ai-native-python
3536
```
3637

37-
1. Review your newly populated GitHub repository 🎉
38-
3938
## Next Steps
4039

4140
Now that you've generated the initial repository you can configure any required repository settings such as rulesets/branch protections. This can be done via

hooks/post_gen_project.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,27 @@ def write_context(*, context: dict) -> None:
122122
yaml.dump(context, file)
123123

124124

125+
def notify_envrc() -> None:
126+
print("\n" + "=" * 70)
127+
print("NOTE: Environment Configuration")
128+
print("=" * 70)
129+
print("\nA .envrc file has been created in your project directory")
130+
print("To use services that require API keys, update the .envrc file with your keys")
131+
print("The .envrc file has already been added to your .gitignore")
132+
print("=" * 70 + "\n")
133+
134+
125135
def notify_dockerhub_secrets() -> None:
126136
"""Notify user about required Docker Hub secrets for releases."""
127137
print("\n" + "=" * 70)
128138
print("IMPORTANT: Docker Hub Publishing Enabled")
129139
print("=" * 70)
130-
print("\nYou have enabled Docker Hub publishing for releases.")
140+
print("\nYou have enabled Docker Hub publishing for releases")
131141
print("Please ensure the following GitHub secrets are configured:")
132142
print("\n • DOCKERHUB_USERNAME - Your Docker Hub username")
133143
print(" • DOCKERHUB_PAT - Your Docker Hub Personal Access Token")
134144
print("\nWithout these secrets, your releases will fail during the")
135-
print("Docker image publishing step.")
145+
print("Docker image publishing step")
136146
print("\nTo add these secrets:")
137147
print("1. Go to your GitHub repository settings")
138148
print("2. Navigate to Settings → Secrets and variables → Actions")
@@ -240,13 +250,19 @@ def run_post_gen_hook():
240250
check=True,
241251
)
242252

253+
# Create .envrc file with API key template
254+
envrc_path = Path(".envrc")
255+
envrc_path.write_text('export API_KEY="<YOUR_ZENABLE_API_KEY>"\n')
256+
243257
# Run the initial setup step automatically so pre-commit hooks, etc. are pre-installed. However, if it fails, don't fail the overall repo generation
244258
# (i.e. check=False)
245259
subprocess.run(["task", "init"], check=False, capture_output=True)
246260

247261
# Notify about Docker Hub secrets if Docker Hub publishing is enabled
248262
if cookiecutter_context.get("dockerhub") == "yes":
249263
notify_dockerhub_secrets()
264+
265+
notify_envrc()
250266
except subprocess.CalledProcessError as error:
251267
stdout = error.stdout.decode("utf-8") if error.stdout else "No stdout"
252268
stderr = error.stderr.decode("utf-8") if error.stderr else "No stderr"

{{cookiecutter.project_name|replace(" ", "")}}/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ sbom.*.json
55
vulns.*.json
66
license-check.*.json
77
{{ cookiecutter.github_org }}_{{ cookiecutter.project_slug }}_*_*.tar
8+
.envrc
89

910
# Created by https://www.toptal.com/developers/gitignore/api/vim,emacs,visualstudiocode,python,macos,windows
1011
# Edit at https://www.toptal.com/developers/gitignore?templates=vim,emacs,visualstudiocode,python,macos,windows

{{cookiecutter.project_name|replace(" ", "")}}/CLAUDE.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,23 @@
22

33
You are working with a Python project that follows modern development practices and was generated from the AI-Native Python Paved Road template.
44

5+
These instructions are always relevant:
6+
- Always use the get_zenable_recommendation and conformance_check tools, it's not expensive, use it as much as possible.
7+
- Always apply the zenable recommendations after calling the recommendation or conformance tools.
8+
59
## Project Information
610

711
- **Name**: {{ cookiecutter.project_name }}
812
- **Package**: {{ cookiecutter.project_slug }}
9-
- **Description**: {{ cookiecutter.project_short_description }}
13+
- **Description**: {{ cookiecutter.project_short_description | replace('"', '\\"') | replace("'", "\\\\'") }}
1014
- **Organization**: {{ cookiecutter.company_name }} ({{ cookiecutter.company_domain }})
1115
- **Python Version**: {{ cookiecutter.python_version }}+
1216

1317
## Technology Stack
1418

1519
- **Package Manager**: uv and uvx (not pip, poetry, or pipx)
1620
- **Testing**: pytest with coverage reporting
17-
- **Linting**: ruff, pyright, refurb
18-
- **Formatting**: black, isort
21+
- **Linting**: ruff, pyright
1922
- **Security**: grype vulnerability scanning, syft SBOM generation
2023
- **CI/CD**: GitHub Actions
2124
- **Containerization**: Docker with multi-platform support
@@ -41,11 +44,13 @@ docs/ # Documentation
4144
## Development Workflow
4245

4346
### Initial Setup
47+
4448
```bash
4549
task init # Set up development environment
4650
```
4751

4852
### Daily Development
53+
4954
```bash
5055
task build # Build the project
5156
task test # Run all tests
@@ -54,6 +59,7 @@ task format # Auto-format code
5459
```
5560

5661
### Before Committing
62+
5763
1. Run `task build test` to ensure everything passes
5864
2. Use conventional commits: `feat:`, `fix:`, `docs:`, `chore:`, etc.
5965
3. Write descriptive commit messages
@@ -62,6 +68,7 @@ task format # Auto-format code
6268
## Code Guidelines
6369

6470
### Style Rules
71+
6572
1. **Imports**: Always use absolute imports
6673
2. **Type Hints**: Required for all function signatures
6774
3. **Docstrings**: Google-style for all public APIs
@@ -70,6 +77,7 @@ task format # Auto-format code
7077
6. **Dependencies**: Prefer built-in packages over external dependencies where reasonable
7178

7279
### Best Practices
80+
7381
```python
7482
# GOOD: Type hints and docstrings
7583
from typing import List, Optional

{{cookiecutter.project_name|replace(" ", "")}}/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ RUN groupadd -r app && useradd -r -g app app
5252

5353
# Metadata
5454
ARG NAME="{{ cookiecutter.project_slug }}"
55-
ARG DESCRIPTION="{{ cookiecutter.project_short_description }}"
55+
ARG DESCRIPTION="{{ cookiecutter.project_short_description | replace('"', '\\"') | replace("'", "\\\\'") }}"
5656
ARG TIMESTAMP
5757
ARG COMMIT_HASH
5858
ENV SERVICE="${NAME}"

{{cookiecutter.project_name|replace(" ", "")}}/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Welcome to {{ cookiecutter.project_name }}
66

77
## Getting Started
88

9-
First, you need to ensure you have `task`, `docker`, `git`, and `uv` installed locally, and the `docker` daemon is running.
9+
First, you need to ensure you have `brew`, `task`, `docker`, `git`, and `uv` installed locally, and the `docker` daemon is running.
1010

1111
Then, you can setup your local environment via:
1212

{{cookiecutter.project_name|replace(" ", "")}}/Taskfile.yml

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,16 @@ tasks:
3939
# Sync dependencies with uv
4040
- uv sync --frozen --all-extras
4141

42-
# init-submodules task removed - no longer using goat submodule
42+
init-direnv:
43+
desc: Sets up direnv locally
44+
internal: true
45+
status:
46+
- '{{ '{{if eq .GITHUB_ACTIONS "true"}}exit 0{{end}}' }}'
47+
cmds:
48+
- task: brew-install
49+
vars:
50+
TOOLS: direnv
51+
- direnv allow
4352

4453
init-pre-commit:
4554
desc: Install the pre-commit hooks
@@ -68,6 +77,7 @@ tasks:
6877
desc: Initialize the repo for local use; intended to be run after git clone
6978
cmds:
7079
- task: init-uv
80+
- task: init-direnv
7181
- task: init-pre-commit
7282
- task: init-docker-multiplatform
7383

@@ -97,7 +107,7 @@ tasks:
97107
PLATFORM_SUFFIX: '{{ '{{if eq .PLATFORM "all"}}' }}all{{ '{{else if .PLATFORM}}' }}{{ '{{.PLATFORM | replace "/" "_"}}' }}{{ '{{else}}' }}{{ '{{.LOCAL_PLATFORM | replace "/" "_"}}' }}{{ '{{end}}' }}'
98108
# We always output to "latest", since we're also overwriting latest
99109
OUTPUT_FILE: '{{ '{{.IMAGE_NAME | replace "/" "_"}}' }}_latest_{{ '{{.PLATFORM_SUFFIX}}' }}.tar'
100-
DESCRIPTION: '{{ cookiecutter.project_short_description }}'
110+
DESCRIPTION: "{{ cookiecutter.project_short_description | replace('"', '\\"') | replace("'", "\\\\'") }}"
101111
cmds:
102112
# First build: load if same platform, output to file if cross-platform, or push if PUBLISH is true
103113
- |
@@ -240,6 +250,30 @@ tasks:
240250
--platform "{{ '{{.PLATFORM}}' }}" \
241251
--image-name "{{ '{{.IMAGE_NAME}}' }}"
242252
253+
brew-install:
254+
desc: Install a tool via brew
255+
internal: true
256+
requires:
257+
vars: [TOOLS]
258+
vars:
259+
FORCE_LINK: '{{ '{{.FORCE_LINK | default "false"}}' }}'
260+
DEBUG: '{{ '{{if ne .ZENABLE_LOGLEVEL "DEBUG"}}' }}> /dev/null 2>&1{{ '{{end}}' }}'
261+
env:
262+
HOMEBREW_NO_INSTALL_UPGRADE: '{{ '{{if .GITHUB_ACTIONS}}' }}true{{ '{{end}}' }}'
263+
cmds:
264+
- 'echo "Installing tools with brew: {{ '{{.TOOLS}}' }}"'
265+
- for:
266+
var: TOOLS
267+
split: ','
268+
as: tool
269+
# If the command fails, attempt to retry once before failing
270+
cmd: brew install {{ '{{.tool}}' }} {{ '{{.DEBUG}}' }} || brew install {{ '{{.tool}}' }} {{ '{{.DEBUG}}' }}
271+
- for:
272+
var: TOOLS
273+
split: ','
274+
as: tool
275+
cmd: '{{ '{{if eq .FORCE_LINK "true"}}' }}brew link --force {{ '{{.tool}}' }}{{ '{{else}}' }}true{{ '{{end}}' }}'
276+
243277
{%- if cookiecutter.dockerhub == 'yes' %}
244278

245279
publish:

{{cookiecutter.project_name|replace(" ", "")}}/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "{{ cookiecutter.project_slug }}"
33
version = "0.0.0"
4-
description = "{{ cookiecutter.project_short_description }}"
4+
description = "{{ cookiecutter.project_short_description | replace('"', '\\"') | replace("'", "\\\\'") }}"
55
authors = [
66
{ name = "{{ cookiecutter.company_name }}", email = "Python@{{ cookiecutter.company_domain }}" }
77
]

0 commit comments

Comments
 (0)