opengate-gate-tree 0.1.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- opengate_gate_tree-0.1.1/.github/PULL_REQUEST_TEMPLATE.md +27 -0
- opengate_gate_tree-0.1.1/.github/copilot-instructions.md +78 -0
- opengate_gate_tree-0.1.1/.github/get_review.sh +119 -0
- opengate_gate_tree-0.1.1/.github/workflows/ci.yaml +48 -0
- opengate_gate_tree-0.1.1/.github/workflows/publish.yml +32 -0
- opengate_gate_tree-0.1.1/.gitignore +18 -0
- opengate_gate_tree-0.1.1/.pre-commit-config.yaml +10 -0
- opengate_gate_tree-0.1.1/CLAUDE.md +99 -0
- opengate_gate_tree-0.1.1/LICENSE +23 -0
- opengate_gate_tree-0.1.1/Makefile +108 -0
- opengate_gate_tree-0.1.1/PKG-INFO +180 -0
- opengate_gate_tree-0.1.1/README.md +160 -0
- opengate_gate_tree-0.1.1/docs/CODING_CONVENTIONS.md +498 -0
- opengate_gate_tree-0.1.1/docs/COMMIT_CONVENTIONS.md +79 -0
- opengate_gate_tree-0.1.1/docs/CONTRIBUTION.md +100 -0
- opengate_gate_tree-0.1.1/docs/ROADMAP.md +260 -0
- opengate_gate_tree-0.1.1/docs/TESTING_CONVENTIONS.md +487 -0
- opengate_gate_tree-0.1.1/docs/VERSION_UPGRADE_CONVENTIONS.md +155 -0
- opengate_gate_tree-0.1.1/pyproject.toml +75 -0
- opengate_gate_tree-0.1.1/scripts/update_version_in_files.sh +101 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/__init__.py +13 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/__main__.py +11 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/cli.py +200 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/config.py +44 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/io/fileformat.py +39 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/logger.py +10 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/logging_setup.py +56 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/tree/branch.py +35 -0
- opengate_gate_tree-0.1.1/src/opengate_gate_tree/tree/gatetree.py +37 -0
- opengate_gate_tree-0.1.1/tests/fixtures/.gitkeep +0 -0
- opengate_gate_tree-0.1.1/tests/integration/.gitkeep +0 -0
- opengate_gate_tree-0.1.1/tests/smoke/test_version.py +55 -0
- opengate_gate_tree-0.1.1/tests/unit/.gitkeep +0 -0
- opengate_gate_tree-0.1.1/tests/unit/test_branch.py +22 -0
- opengate_gate_tree-0.1.1/tests/unit/test_cli.py +112 -0
- opengate_gate_tree-0.1.1/tests/unit/test_config.py +36 -0
- opengate_gate_tree-0.1.1/tests/unit/test_fileformat.py +18 -0
- opengate_gate_tree-0.1.1/tests/unit/test_gatetree.py +18 -0
- opengate_gate_tree-0.1.1/tests/unit/test_logger.py +18 -0
- opengate_gate_tree-0.1.1/tests/unit/test_logging_setup.py +33 -0
- opengate_gate_tree-0.1.1/tests/unit/test_main_entrypoint.py +29 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## Description
|
|
2
|
+
Brief description of what this PR does.
|
|
3
|
+
|
|
4
|
+
## Related Issues
|
|
5
|
+
Closes #123
|
|
6
|
+
Related to #456
|
|
7
|
+
|
|
8
|
+
## Changes
|
|
9
|
+
- Change 1
|
|
10
|
+
- Change 2
|
|
11
|
+
- Change 3
|
|
12
|
+
|
|
13
|
+
## Type of Change
|
|
14
|
+
- [ ] Bug fix (non-breaking)
|
|
15
|
+
- [ ] New feature (non-breaking)
|
|
16
|
+
- [ ] Breaking change
|
|
17
|
+
- [ ] Documentation update
|
|
18
|
+
|
|
19
|
+
## Testing
|
|
20
|
+
Describe tests added or how changes were tested.
|
|
21
|
+
|
|
22
|
+
## Checklist
|
|
23
|
+
- [ ] Code follows style guidelines
|
|
24
|
+
- [ ] Tests added and passing
|
|
25
|
+
- [ ] Documentation updated
|
|
26
|
+
- [ ] Commit messages are clear
|
|
27
|
+
- [ ] No merge conflicts
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Copilot Instructions
|
|
2
|
+
|
|
3
|
+
These instructions apply to all changes in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Context
|
|
6
|
+
|
|
7
|
+
- Package name: `opengate-gate-tree`
|
|
8
|
+
- Source root: `src/opengate_gate_tree`
|
|
9
|
+
- Supported Python versions: 3.11-3.14
|
|
10
|
+
- Environment and dependency manager: `uv`
|
|
11
|
+
|
|
12
|
+
## Development Workflow
|
|
13
|
+
|
|
14
|
+
- Prefer Make targets for common tasks:
|
|
15
|
+
- `make init`
|
|
16
|
+
- `make lint`
|
|
17
|
+
- `make format`
|
|
18
|
+
- `make typecheck`
|
|
19
|
+
- `make test`
|
|
20
|
+
- `make check`
|
|
21
|
+
- Keep changes focused and minimal.
|
|
22
|
+
- Do not introduce unrelated refactors in the same change.
|
|
23
|
+
|
|
24
|
+
## Repository Standards
|
|
25
|
+
|
|
26
|
+
- Follow coding conventions from [../docs/CODING_CONVENTIONS.md](../docs/CODING_CONVENTIONS.md).
|
|
27
|
+
- Follow testing conventions from [../docs/TESTING_CONVENTIONS.md](../docs/TESTING_CONVENTIONS.md).
|
|
28
|
+
|
|
29
|
+
## Code Quality Requirements
|
|
30
|
+
|
|
31
|
+
- Keep code and user-facing messages in English.
|
|
32
|
+
- Follow type hints consistently; this repository uses strict mypy settings.
|
|
33
|
+
- Keep line length within Ruff limits (100 characters).
|
|
34
|
+
- Preserve existing module structure and naming conventions.
|
|
35
|
+
- Treat [../docs/CODING_CONVENTIONS.md](../docs/CODING_CONVENTIONS.md) as authoritative for style decisions.
|
|
36
|
+
|
|
37
|
+
## Testing Requirements
|
|
38
|
+
|
|
39
|
+
- Add or update tests when behavior changes.
|
|
40
|
+
- Place unit tests under `tests/unit`.
|
|
41
|
+
- Ensure tests target current modules from `opengate_gate_tree` (not legacy project names).
|
|
42
|
+
- Avoid adding test dependencies that are not declared in `pyproject.toml`.
|
|
43
|
+
- Treat [../docs/TESTING_CONVENTIONS.md](../docs/TESTING_CONVENTIONS.md) as authoritative for test structure.
|
|
44
|
+
|
|
45
|
+
## Validation Before Finishing
|
|
46
|
+
|
|
47
|
+
Run full validation before finalizing code changes:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
make check
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
If pre-commit is enabled, ensure hooks pass:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv run pre-commit run --all-files
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Versioning and Release Rules
|
|
60
|
+
|
|
61
|
+
- For version bumps, use:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
bash script/update_version_in_files.sh "$VERSION"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- Follow the release procedure in `docs/VERSION_UPGRADE_CONVENTIONS.md`.
|
|
68
|
+
- Release publication is allowed only on `main` and only by repository admins.
|
|
69
|
+
|
|
70
|
+
## Commit and PR Hygiene
|
|
71
|
+
|
|
72
|
+
- Follow commit format rules from `docs/COMMIT_CONVENTIONS.md`.
|
|
73
|
+
- Keep commit messages explicit and scoped.
|
|
74
|
+
- Ensure PR descriptions use `.github/PULL_REQUEST_TEMPLATE.md`.
|
|
75
|
+
|
|
76
|
+
## Agent configuration
|
|
77
|
+
|
|
78
|
+
Additional generalised settings for agents are in a directory `.agents`
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
6
|
+
echo "Error: required tool 'gh' is not installed." >&2
|
|
7
|
+
exit 1
|
|
8
|
+
fi
|
|
9
|
+
|
|
10
|
+
if ! command -v jq >/dev/null 2>&1; then
|
|
11
|
+
echo "Error: required tool 'jq' is not installed." >&2
|
|
12
|
+
exit 1
|
|
13
|
+
fi
|
|
14
|
+
|
|
15
|
+
if ! gh auth status >/dev/null 2>&1; then
|
|
16
|
+
echo "Error: you are not signed in to gh. Run: gh auth login" >&2
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
|
21
|
+
REPO_FULL="$(gh repo view --json nameWithOwner -q .nameWithOwner)"
|
|
22
|
+
OWNER="${REPO_FULL%/*}"
|
|
23
|
+
REPO="${REPO_FULL#*/}"
|
|
24
|
+
|
|
25
|
+
OUTPUT_DIR=".tmp/code-reviews"
|
|
26
|
+
mkdir -p "$OUTPUT_DIR"
|
|
27
|
+
|
|
28
|
+
BRANCH_SAFE="$(echo "$BRANCH" | sed -E 's/[^A-Za-z0-9._-]+/-/g')"
|
|
29
|
+
if [[ -z "$BRANCH_SAFE" ]]; then
|
|
30
|
+
BRANCH_SAFE="unknown-branch"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
FETCH_DATE="$(date '+%Y%m%d-%H%M%S')"
|
|
34
|
+
FETCH_DAY="${FETCH_DATE%%-*}"
|
|
35
|
+
EXISTING_COUNT="$({
|
|
36
|
+
find "$OUTPUT_DIR" -maxdepth 1 -type f \
|
|
37
|
+
-name "pr-code-review-${BRANCH_SAFE}-${FETCH_DAY}-*.md"
|
|
38
|
+
} | wc -l | tr -d '[:space:]')"
|
|
39
|
+
ORDER_NUMBER="$(printf '%02d' "$((EXISTING_COUNT + 1))")"
|
|
40
|
+
OUTPUT_FILE="${OUTPUT_DIR}/pr-code-review-${BRANCH_SAFE}-${FETCH_DATE}-${ORDER_NUMBER}.md"
|
|
41
|
+
|
|
42
|
+
PRS_JSON="$(gh pr list --state open --head "$BRANCH" --json number,title,url,headRefName,author 2>/dev/null || true)"
|
|
43
|
+
|
|
44
|
+
if [[ -z "$PRS_JSON" || "$PRS_JSON" == "[]" ]]; then
|
|
45
|
+
{
|
|
46
|
+
echo "# Review tasks"
|
|
47
|
+
echo
|
|
48
|
+
echo "No open PR found for branch: $BRANCH."
|
|
49
|
+
} >"$OUTPUT_FILE"
|
|
50
|
+
echo "Saved: $OUTPUT_FILE"
|
|
51
|
+
exit 0
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
PR_NUMBERS="$(echo "$PRS_JSON" | jq -r '.[].number')"
|
|
55
|
+
FIRST_PR_NUMBER="$(echo "$PR_NUMBERS" | head -n1)"
|
|
56
|
+
|
|
57
|
+
GRAPHQL_QUERY='query($owner:String!, $repo:String!, $number:Int!) {
|
|
58
|
+
repository(owner:$owner, name:$repo) {
|
|
59
|
+
pullRequest(number:$number) {
|
|
60
|
+
number
|
|
61
|
+
title
|
|
62
|
+
url
|
|
63
|
+
headRefName
|
|
64
|
+
reviewThreads(first: 100) {
|
|
65
|
+
nodes {
|
|
66
|
+
isResolved
|
|
67
|
+
isOutdated
|
|
68
|
+
path
|
|
69
|
+
line
|
|
70
|
+
startLine
|
|
71
|
+
comments(first: 100) {
|
|
72
|
+
nodes {
|
|
73
|
+
author { login }
|
|
74
|
+
body
|
|
75
|
+
url
|
|
76
|
+
createdAt
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}'
|
|
84
|
+
|
|
85
|
+
PR_JSON="$(gh api graphql -f query="$GRAPHQL_QUERY" -F owner="$OWNER" -F repo="$REPO" -F number="$FIRST_PR_NUMBER")"
|
|
86
|
+
|
|
87
|
+
UNRESOLVED_COUNT="$(echo "$PR_JSON" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select(.isResolved == false)] | length')"
|
|
88
|
+
|
|
89
|
+
{
|
|
90
|
+
echo "# Review tasks"
|
|
91
|
+
echo
|
|
92
|
+
echo "Repository: \`$REPO_FULL\` "
|
|
93
|
+
echo "Branch: \`$BRANCH\` "
|
|
94
|
+
echo "PR: [#${FIRST_PR_NUMBER}]($(echo "$PR_JSON" | jq -r '.data.repository.pullRequest.url')) - $(echo "$PR_JSON" | jq -r '.data.repository.pullRequest.title')"
|
|
95
|
+
echo
|
|
96
|
+
echo "## Unresolved threads"
|
|
97
|
+
echo
|
|
98
|
+
|
|
99
|
+
if [[ "$UNRESOLVED_COUNT" -eq 0 ]]; then
|
|
100
|
+
echo "No unresolved threads ✅"
|
|
101
|
+
else
|
|
102
|
+
echo "$PR_JSON" | jq -r '
|
|
103
|
+
.data.repository.pullRequest.reviewThreads.nodes
|
|
104
|
+
| map(select(.isResolved == false))
|
|
105
|
+
| to_entries[]
|
|
106
|
+
| .value as $t
|
|
107
|
+
| $t.comments.nodes[0] as $c
|
|
108
|
+
| "- [ ] "
|
|
109
|
+
+ "[" + ($t.path // "(brak pliku)")
|
|
110
|
+
+ (if ($t.line // $t.startLine) then ":L" + (($t.line // $t.startLine)|tostring) else "" end)
|
|
111
|
+
+ "](" + ($c.url // "") + ")"
|
|
112
|
+
+ " — @" + ($c.author.login // "unknown")
|
|
113
|
+
+ (if $t.isOutdated then " *(outdated)*" else "" end)
|
|
114
|
+
+ "\n > " + (($c.body // "") | gsub("\n"; " ") | gsub("\r"; " ") | .[0:50000])
|
|
115
|
+
'
|
|
116
|
+
fi
|
|
117
|
+
} >"$OUTPUT_FILE"
|
|
118
|
+
|
|
119
|
+
echo "Saved: $OUTPUT_FILE"
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
- develop
|
|
8
|
+
pull_request:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
- develop
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
|
|
17
|
+
concurrency:
|
|
18
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
19
|
+
cancel-in-progress: true
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
check:
|
|
23
|
+
name: check (Python ${{ matrix.python-version }})
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
python-version: ["3.11", "3.12", "3.13", "3.14"]
|
|
29
|
+
|
|
30
|
+
steps:
|
|
31
|
+
- name: Checkout repository
|
|
32
|
+
uses: actions/checkout@v4
|
|
33
|
+
|
|
34
|
+
- name: Set up Python
|
|
35
|
+
uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: ${{ matrix.python-version }}
|
|
38
|
+
|
|
39
|
+
- name: Set up uv
|
|
40
|
+
uses: astral-sh/setup-uv@v5
|
|
41
|
+
with:
|
|
42
|
+
enable-cache: true
|
|
43
|
+
|
|
44
|
+
- name: Install dependencies
|
|
45
|
+
run: make init
|
|
46
|
+
|
|
47
|
+
- name: Run full validation
|
|
48
|
+
run: make check
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- name: Install uv
|
|
13
|
+
uses: astral-sh/setup-uv@v5
|
|
14
|
+
- name: Build sdist and wheel
|
|
15
|
+
run: uv build
|
|
16
|
+
- uses: actions/upload-artifact@v4
|
|
17
|
+
with:
|
|
18
|
+
name: dist
|
|
19
|
+
path: dist/
|
|
20
|
+
|
|
21
|
+
publish:
|
|
22
|
+
needs: build
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
environment: pypi
|
|
25
|
+
permissions:
|
|
26
|
+
id-token: write
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/download-artifact@v4
|
|
29
|
+
with:
|
|
30
|
+
name: dist
|
|
31
|
+
path: dist/
|
|
32
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides project-level instructions for Claude Code.
|
|
4
|
+
|
|
5
|
+
## Scope and priorities
|
|
6
|
+
|
|
7
|
+
- Apply these rules to all work in this repository.
|
|
8
|
+
- Keep instructions specific, verifiable, and concise.
|
|
9
|
+
- Prefer project conventions over generic defaults.
|
|
10
|
+
|
|
11
|
+
## Project snapshot
|
|
12
|
+
|
|
13
|
+
- Package: opengate-gate-tree
|
|
14
|
+
- Source root: src/opengate_gate_tree
|
|
15
|
+
- Tests root: tests/unit
|
|
16
|
+
- Python support: 3.11-3.14
|
|
17
|
+
- Tooling: uv, ruff, mypy, pytest, pre-commit
|
|
18
|
+
|
|
19
|
+
## Required workflow
|
|
20
|
+
|
|
21
|
+
Use repository Make targets when available:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
make init
|
|
25
|
+
make lint
|
|
26
|
+
make format
|
|
27
|
+
make typecheck
|
|
28
|
+
make test
|
|
29
|
+
make check
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If CLI tools are needed, run them via uv in this repository:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
uv run <tool>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Non-negotiable checks before finishing changes
|
|
39
|
+
|
|
40
|
+
Run:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
make check
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
If pre-commit is enabled, also run:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv run pre-commit run --all-files
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Do not consider work complete while these checks fail.
|
|
53
|
+
|
|
54
|
+
## Coding rules
|
|
55
|
+
|
|
56
|
+
- Keep code, comments, docs, and user-facing messages in English.
|
|
57
|
+
- Keep edits minimal and focused; avoid unrelated refactors.
|
|
58
|
+
- Follow strict type hints; this project uses strict mypy settings.
|
|
59
|
+
- Keep line length within Ruff limits (100).
|
|
60
|
+
- Preserve current package/module naming and folder layout.
|
|
61
|
+
|
|
62
|
+
Authoritative coding standard:
|
|
63
|
+
- docs/CODING_CONVENTIONS.md
|
|
64
|
+
|
|
65
|
+
## Testing rules
|
|
66
|
+
|
|
67
|
+
- Add or update tests when behavior changes.
|
|
68
|
+
- Keep unit tests under tests/unit.
|
|
69
|
+
- Target current modules from opengate_gate_macro_fold.
|
|
70
|
+
- Do not reintroduce legacy imports or names from other projects.
|
|
71
|
+
|
|
72
|
+
Authoritative testing standard:
|
|
73
|
+
- docs/TESTING_CONVENTIONS.md
|
|
74
|
+
|
|
75
|
+
## Versioning and release
|
|
76
|
+
|
|
77
|
+
- Version releases are allowed only on main and only by admins.
|
|
78
|
+
- For version updates in files, use:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
bash script/update_version_in_files.sh "$VERSION"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Authoritative release process:
|
|
85
|
+
- docs/VERSION_UPGRADE_CONVENTIONS.md
|
|
86
|
+
|
|
87
|
+
## Commit and PR hygiene
|
|
88
|
+
|
|
89
|
+
- Follow docs/COMMIT_CONVENTIONS.md for commit message format.
|
|
90
|
+
- Use .github/PULL_REQUEST_TEMPLATE.md for PR descriptions.
|
|
91
|
+
|
|
92
|
+
## Repository-specific pitfalls to avoid
|
|
93
|
+
|
|
94
|
+
- Do not add obsolete console script aliases from older projects.
|
|
95
|
+
- Ensure tests and docs match the current package name and module paths.
|
|
96
|
+
|
|
97
|
+
## Agent configuration
|
|
98
|
+
|
|
99
|
+
Additional generalised settings for agents are in a directory `.agents`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
**Project:** opengate-gate-tree
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2026 Mateusz Jakub Bała
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# FILE: Makefile
|
|
2
|
+
# ABOUT: Project helper tasks: installation, validation, and worktree
|
|
3
|
+
# management for feature branches created from develop.
|
|
4
|
+
# USAGE:
|
|
5
|
+
# make init | install | install-user | test | lint | format | typecheck | check
|
|
6
|
+
# make worktree BRANCH_NAME=feature/description
|
|
7
|
+
# make switch-to-worktree BRANCH_NAME=feature/description
|
|
8
|
+
|
|
9
|
+
SHELL := /bin/bash
|
|
10
|
+
|
|
11
|
+
# Parent directory for worktrees and directory for lock files.
|
|
12
|
+
WORKTREE_ROOT ?= ./worktrees
|
|
13
|
+
WORKTREE_LOCKS_DIR ?= .tmp/worktree-locks
|
|
14
|
+
|
|
15
|
+
.PHONY: init install install-user test lint format typecheck check worktree switch-to-worktree
|
|
16
|
+
|
|
17
|
+
# Install dependencies and create the virtual environment (uv).
|
|
18
|
+
init:
|
|
19
|
+
uv sync
|
|
20
|
+
|
|
21
|
+
# Install project dependencies and package into the local .venv.
|
|
22
|
+
install: init
|
|
23
|
+
@echo "Installed in local virtual environment: .venv"
|
|
24
|
+
@echo "Run via uv: uv run opengate-gate-tree --help"
|
|
25
|
+
@echo "Or activate the environment: source .venv/bin/activate"
|
|
26
|
+
|
|
27
|
+
# Install the package for the current user (outside project .venv).
|
|
28
|
+
install-user:
|
|
29
|
+
python3 -m pip install --user -e .
|
|
30
|
+
@echo "Installed in user site-packages (--user)."
|
|
31
|
+
@echo "If needed, add ~/.local/bin to PATH."
|
|
32
|
+
|
|
33
|
+
# Run the full test suite.
|
|
34
|
+
test:
|
|
35
|
+
uv run pytest
|
|
36
|
+
|
|
37
|
+
# Check code style (lint).
|
|
38
|
+
lint:
|
|
39
|
+
uv run ruff check
|
|
40
|
+
|
|
41
|
+
# Format code.
|
|
42
|
+
format:
|
|
43
|
+
uv run ruff format
|
|
44
|
+
|
|
45
|
+
# Static type checking.
|
|
46
|
+
typecheck:
|
|
47
|
+
uv run mypy src/
|
|
48
|
+
|
|
49
|
+
# Full local validation: lint, formatting check, types, tests.
|
|
50
|
+
check:
|
|
51
|
+
uv run ruff check
|
|
52
|
+
uv run ruff format --check
|
|
53
|
+
uv run mypy src/
|
|
54
|
+
uv run pytest
|
|
55
|
+
|
|
56
|
+
# Create a worktree for the given branch if it does not already exist.
|
|
57
|
+
worktree:
|
|
58
|
+
@if [[ -z "$(BRANCH_NAME)" ]]; then \
|
|
59
|
+
echo "Error: set BRANCH_NAME, e.g. make worktree BRANCH_NAME=worktree/branch/name." >&2; \
|
|
60
|
+
exit 1; \
|
|
61
|
+
fi
|
|
62
|
+
@WORKTREE_DIR="$(WORKTREE_ROOT)/$$(echo "$(BRANCH_NAME)" | tr '/' '-')"; \
|
|
63
|
+
mkdir -p "$(WORKTREE_ROOT)"; \
|
|
64
|
+
if git worktree list --porcelain | grep -Fxq "branch refs/heads/$(BRANCH_NAME)"; then \
|
|
65
|
+
echo "Worktree for branch $(BRANCH_NAME) already exists."; \
|
|
66
|
+
exit 0; \
|
|
67
|
+
fi; \
|
|
68
|
+
if git show-ref --verify --quiet "refs/heads/$(BRANCH_NAME)"; then \
|
|
69
|
+
git worktree add "$$WORKTREE_DIR" "$(BRANCH_NAME)"; \
|
|
70
|
+
else \
|
|
71
|
+
git worktree add -b "$(BRANCH_NAME)" "$$WORKTREE_DIR" develop; \
|
|
72
|
+
fi; \
|
|
73
|
+
echo "Created worktree: $$WORKTREE_DIR (branch: $(BRANCH_NAME))."
|
|
74
|
+
|
|
75
|
+
# Switch to an existing worktree if it is not locked by another instance.
|
|
76
|
+
switch-to-worktree:
|
|
77
|
+
@if [[ -z "$(BRANCH_NAME)" ]]; then \
|
|
78
|
+
echo "Error: set BRANCH_NAME, e.g. make switch-to-worktree BRANCH_NAME=worktree/branch/name." >&2; \
|
|
79
|
+
exit 1; \
|
|
80
|
+
fi
|
|
81
|
+
@if ! git show-ref --verify --quiet "refs/heads/$(BRANCH_NAME)"; then \
|
|
82
|
+
echo "Error: the specified branch does not exist: $(BRANCH_NAME)." >&2; \
|
|
83
|
+
exit 1; \
|
|
84
|
+
fi
|
|
85
|
+
@WORKTREE_DIR="$$(git worktree list --porcelain | awk -v target="refs/heads/$(BRANCH_NAME)" '\
|
|
86
|
+
$$1=="worktree" { path=$$2 } \
|
|
87
|
+
$$1=="branch" && $$2==target { print path; exit }')"; \
|
|
88
|
+
if [[ -z "$$WORKTREE_DIR" ]]; then \
|
|
89
|
+
echo "Error: no worktree exists for branch $(BRANCH_NAME). First run make worktree BRANCH_NAME=$(BRANCH_NAME)." >&2; \
|
|
90
|
+
exit 1; \
|
|
91
|
+
fi; \
|
|
92
|
+
LOCK_FILE="$(WORKTREE_LOCKS_DIR)/$$(echo "$(BRANCH_NAME)" | tr '/' '-').lock"; \
|
|
93
|
+
mkdir -p "$(WORKTREE_LOCKS_DIR)"; \
|
|
94
|
+
if [[ -f "$$LOCK_FILE" ]]; then \
|
|
95
|
+
LOCK_PID="$$(cat "$$LOCK_FILE")"; \
|
|
96
|
+
if [[ -n "$$LOCK_PID" ]] && kill -0 "$$LOCK_PID" 2>/dev/null; then \
|
|
97
|
+
echo "Error: the worktree is already locked by another instance (PID: $$LOCK_PID)." >&2; \
|
|
98
|
+
echo "How to release it: stop the process with PID $$LOCK_PID (for example, close the shell holding the lock)." >&2; \
|
|
99
|
+
exit 1; \
|
|
100
|
+
fi; \
|
|
101
|
+
rm -f "$$LOCK_FILE"; \
|
|
102
|
+
fi; \
|
|
103
|
+
echo "$$BASHPID" > "$$LOCK_FILE"; \
|
|
104
|
+
cleanup() { rm -f "$$LOCK_FILE"; }; \
|
|
105
|
+
trap cleanup EXIT INT TERM; \
|
|
106
|
+
echo "Switched to $$WORKTREE_DIR. To release the lock, close this shell."; \
|
|
107
|
+
cd "$$WORKTREE_DIR"; \
|
|
108
|
+
"$${SHELL:-/bin/bash}" -i
|