git-worktree-wrapper 0.1.0__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.
- git_worktree_wrapper-0.1.0/.github/BRANCH_PROTECTION.md +112 -0
- git_worktree_wrapper-0.1.0/.github/scripts/setup-branch-protection.sh +85 -0
- git_worktree_wrapper-0.1.0/.github/workflows/ci.yml +64 -0
- git_worktree_wrapper-0.1.0/.github/workflows/release.yml +72 -0
- git_worktree_wrapper-0.1.0/.gitignore +34 -0
- git_worktree_wrapper-0.1.0/.opencode/skills/sync-docs-en-to-ru/SKILL.md +114 -0
- git_worktree_wrapper-0.1.0/.python-version +1 -0
- git_worktree_wrapper-0.1.0/AGENTS.md +283 -0
- git_worktree_wrapper-0.1.0/CHANGELOG.md +38 -0
- git_worktree_wrapper-0.1.0/CONSTITUTION.md +52 -0
- git_worktree_wrapper-0.1.0/CONTEXT.md +114 -0
- git_worktree_wrapper-0.1.0/PKG-INFO +473 -0
- git_worktree_wrapper-0.1.0/README.md +446 -0
- git_worktree_wrapper-0.1.0/README.ru.md +447 -0
- git_worktree_wrapper-0.1.0/docs/adr/0001-simpleeval-with-strict-subclass.md +16 -0
- git_worktree_wrapper-0.1.0/docs/adr/0002-ruamel-yaml-round-trip.md +27 -0
- git_worktree_wrapper-0.1.0/docs/adr/0003-stdlib-xdg-config-directory.md +41 -0
- git_worktree_wrapper-0.1.0/docs/adr/0004-subprocess-for-git-operations.md +26 -0
- git_worktree_wrapper-0.1.0/docs/adr/0005-argparse-built-in-shell-completion.md +27 -0
- git_worktree_wrapper-0.1.0/docs/adr/0006-regex-preprocessor-for-templates.md +17 -0
- git_worktree_wrapper-0.1.0/docs/adr/0007-single-cli-project-structure.md +16 -0
- git_worktree_wrapper-0.1.0/docs/adr/0008-stream-both-streams-by-default.md +22 -0
- git_worktree_wrapper-0.1.0/docs/adr/0009-project-rule-evaluation-context.md +59 -0
- git_worktree_wrapper-0.1.0/docs/adr/0010-action-failure-semantics.md +36 -0
- git_worktree_wrapper-0.1.0/docs/adr/0011-before-remove-action-kind.md +47 -0
- git_worktree_wrapper-0.1.0/docs/adr/0012-unified-copy-action-and-path-template-args.md +67 -0
- git_worktree_wrapper-0.1.0/docs/adr/0013-fish-prompt-repaint.md +3 -0
- git_worktree_wrapper-0.1.0/docs/adr/0014-pypi-trusted-publishing.md +37 -0
- git_worktree_wrapper-0.1.0/docs/architecture-diagram.html +111 -0
- git_worktree_wrapper-0.1.0/docs/architecture.md +176 -0
- git_worktree_wrapper-0.1.0/docs/releasing.md +145 -0
- git_worktree_wrapper-0.1.0/pyproject.toml +100 -0
- git_worktree_wrapper-0.1.0/src/gww/__init__.py +3 -0
- git_worktree_wrapper-0.1.0/src/gww/actions/__init__.py +224 -0
- git_worktree_wrapper-0.1.0/src/gww/actions/types.py +187 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/add.py +122 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/clone.py +97 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/init.py +147 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/migrate.py +81 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/pull.py +62 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/commands/remove.py +153 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/context.py +382 -0
- git_worktree_wrapper-0.1.0/src/gww/cli/main.py +285 -0
- git_worktree_wrapper-0.1.0/src/gww/config/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/src/gww/config/loader.py +305 -0
- git_worktree_wrapper-0.1.0/src/gww/config/resolver.py +188 -0
- git_worktree_wrapper-0.1.0/src/gww/config/validator.py +344 -0
- git_worktree_wrapper-0.1.0/src/gww/git/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/src/gww/git/branch.py +264 -0
- git_worktree_wrapper-0.1.0/src/gww/git/repository.py +403 -0
- git_worktree_wrapper-0.1.0/src/gww/git/worktree.py +395 -0
- git_worktree_wrapper-0.1.0/src/gww/migration/__init__.py +44 -0
- git_worktree_wrapper-0.1.0/src/gww/migration/executor.py +342 -0
- git_worktree_wrapper-0.1.0/src/gww/migration/planner.py +260 -0
- git_worktree_wrapper-0.1.0/src/gww/template/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/src/gww/template/evaluator.py +281 -0
- git_worktree_wrapper-0.1.0/src/gww/template/functions.py +378 -0
- git_worktree_wrapper-0.1.0/src/gww/utils/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/src/gww/utils/shell.py +894 -0
- git_worktree_wrapper-0.1.0/src/gww/utils/uri.py +171 -0
- git_worktree_wrapper-0.1.0/src/gww/utils/xdg.py +71 -0
- git_worktree_wrapper-0.1.0/tests/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/tests/conftest.py +52 -0
- git_worktree_wrapper-0.1.0/tests/integration/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_cli_commands.py +235 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_clone_flow.py +366 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_migration.py +1443 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_remove_command.py +550 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_shell_aliases.py +1767 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_streaming_output.py +374 -0
- git_worktree_wrapper-0.1.0/tests/integration/test_worktree_management.py +530 -0
- git_worktree_wrapper-0.1.0/tests/unit/__init__.py +1 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_actions_apply.py +564 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_actions_executor.py +320 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_cli_parser.py +62 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_config_loader.py +272 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_config_resolver.py +1000 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_git_branch.py +276 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_git_repository.py +586 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_git_worktree.py +401 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_gitfile.py +75 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_migrate.py +43 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_migration_executor.py +254 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_migration_planner.py +247 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_shell_completion.py +742 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_stale_alias_warning.py +316 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_template_functions.py +903 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_uri_parsing.py +209 -0
- git_worktree_wrapper-0.1.0/tests/unit/test_xdg.py +268 -0
- git_worktree_wrapper-0.1.0/uv.lock +397 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Branch Protection Setup
|
|
2
|
+
|
|
3
|
+
This document describes how to set up branch protection for the `main` branch using GitHub's API or web interface.
|
|
4
|
+
|
|
5
|
+
## Option 1: Using GitHub Web Interface (Recommended)
|
|
6
|
+
|
|
7
|
+
1. Go to your repository on GitHub
|
|
8
|
+
2. Navigate to **Settings** → **Branches**
|
|
9
|
+
3. Click **Add rule** or edit the existing rule for `main`
|
|
10
|
+
4. Configure the following settings:
|
|
11
|
+
- **Branch name pattern**: `main`
|
|
12
|
+
- ✅ **Require a pull request before merging**
|
|
13
|
+
- ✅ Require approvals: `1` (or more)
|
|
14
|
+
- ✅ Dismiss stale pull request approvals when new commits are pushed
|
|
15
|
+
- ✅ **Require status checks to pass before merging**
|
|
16
|
+
- ✅ Require branches to be up to date before merging
|
|
17
|
+
- Select required status checks:
|
|
18
|
+
- `Test (Python 3.11) / ubuntu-latest`
|
|
19
|
+
- `Test (Python 3.11) / macos-latest`
|
|
20
|
+
- `Test (Python 3.12) / ubuntu-latest`
|
|
21
|
+
- `Test (Python 3.12) / macos-latest`
|
|
22
|
+
- `Test (Python 3.13) / ubuntu-latest`
|
|
23
|
+
- `Test (Python 3.13) / macos-latest`
|
|
24
|
+
- `Lint`
|
|
25
|
+
- ✅ **Require conversation resolution before merging**
|
|
26
|
+
- ✅ **Do not allow bypassing the above settings**
|
|
27
|
+
- ✅ **Restrict who can push to matching branches** (optional, but recommended)
|
|
28
|
+
- ✅ **Allow force pushes** (unchecked - disable force pushes)
|
|
29
|
+
- ✅ **Allow deletions** (unchecked - prevent branch deletion)
|
|
30
|
+
|
|
31
|
+
## Option 2: Using GitHub CLI
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Install GitHub CLI if not already installed
|
|
35
|
+
# brew install gh # macOS
|
|
36
|
+
# apt install gh # Linux
|
|
37
|
+
|
|
38
|
+
# Authenticate
|
|
39
|
+
gh auth login
|
|
40
|
+
|
|
41
|
+
# Set branch protection rules
|
|
42
|
+
gh api repos/:owner/:repo/branches/main/protection \
|
|
43
|
+
--method PUT \
|
|
44
|
+
--field required_status_checks='{"strict":true,"contexts":["Test (Python 3.11) / ubuntu-latest","Test (Python 3.11) / macos-latest","Test (Python 3.12) / ubuntu-latest","Test (Python 3.12) / macos-latest","Test (Python 3.13) / ubuntu-latest","Test (Python 3.13) / macos-latest","Lint"]}' \
|
|
45
|
+
--field enforce_admins=true \
|
|
46
|
+
--field required_pull_request_reviews='{"required_approving_review_count":1,"dismiss_stale_reviews":true}' \
|
|
47
|
+
--field restrictions=null \
|
|
48
|
+
--field allow_force_pushes=false \
|
|
49
|
+
--field allow_deletions=false
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Replace `:owner` and `:repo` with your GitHub username and repository name.
|
|
53
|
+
|
|
54
|
+
## Option 3: Using GitHub API with curl
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# Set your GitHub token
|
|
58
|
+
export GITHUB_TOKEN=your_token_here
|
|
59
|
+
|
|
60
|
+
# Set branch protection
|
|
61
|
+
curl -X PUT \
|
|
62
|
+
-H "Accept: application/vnd.github+json" \
|
|
63
|
+
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
|
64
|
+
-H "X-GitHub-Api-Version: 2022-11-28" \
|
|
65
|
+
https://api.github.com/repos/vadimvolk/git-worktree-wrapper/branches/main/protection \
|
|
66
|
+
-d '{
|
|
67
|
+
"required_status_checks": {
|
|
68
|
+
"strict": true,
|
|
69
|
+
"contexts": [
|
|
70
|
+
"Test (Python 3.11) / ubuntu-latest",
|
|
71
|
+
"Test (Python 3.11) / macos-latest",
|
|
72
|
+
"Test (Python 3.12) / ubuntu-latest",
|
|
73
|
+
"Test (Python 3.12) / macos-latest",
|
|
74
|
+
"Test (Python 3.13) / ubuntu-latest",
|
|
75
|
+
"Test (Python 3.13) / macos-latest",
|
|
76
|
+
"Lint"
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
"enforce_admins": true,
|
|
80
|
+
"required_pull_request_reviews": {
|
|
81
|
+
"required_approving_review_count": 1,
|
|
82
|
+
"dismiss_stale_reviews": true
|
|
83
|
+
},
|
|
84
|
+
"restrictions": null,
|
|
85
|
+
"allow_force_pushes": false,
|
|
86
|
+
"allow_deletions": false
|
|
87
|
+
}'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Verification
|
|
91
|
+
|
|
92
|
+
After setting up branch protection, verify it works:
|
|
93
|
+
|
|
94
|
+
1. Create a test branch: `git checkout -b test-branch-protection`
|
|
95
|
+
2. Make a change and push: `git push origin test-branch-protection`
|
|
96
|
+
3. Create a pull request to `main`
|
|
97
|
+
4. Verify that:
|
|
98
|
+
- The PR cannot be merged until CI tests pass
|
|
99
|
+
- The PR requires at least one approval
|
|
100
|
+
- Force push to `main` is blocked
|
|
101
|
+
|
|
102
|
+
## Notes
|
|
103
|
+
|
|
104
|
+
- The CI workflow runs on all branches (push events) and on pull requests to `main`
|
|
105
|
+
- After merging to `main`, the CI will run again to verify the merge
|
|
106
|
+
- Status checks must pass before merging pull requests
|
|
107
|
+
- **Important**: After the first CI run completes, check the actual status check names in GitHub:
|
|
108
|
+
1. Go to any pull request or commit
|
|
109
|
+
2. View the "Checks" tab
|
|
110
|
+
3. Note the exact names of the status checks (e.g., "Test (Python 3.11)", "Lint")
|
|
111
|
+
4. Update the branch protection settings with the exact check names
|
|
112
|
+
- Alternatively, you can require only the job names (`test` and `lint`) if GitHub supports that, or require "any status check" to pass
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Setup branch protection for main branch using GitHub CLI
|
|
3
|
+
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
REPO_OWNER="${GITHUB_REPOSITORY_OWNER:-vadimvolk}"
|
|
7
|
+
REPO_NAME="${GITHUB_REPOSITORY_NAME:-git-worktree-wrapper}"
|
|
8
|
+
BRANCH="main"
|
|
9
|
+
|
|
10
|
+
echo "Setting up branch protection for ${REPO_OWNER}/${REPO_NAME}:${BRANCH}"
|
|
11
|
+
|
|
12
|
+
# Check if gh CLI is installed
|
|
13
|
+
if ! command -v gh &> /dev/null; then
|
|
14
|
+
echo "Error: GitHub CLI (gh) is not installed."
|
|
15
|
+
echo "Install it with: brew install gh # macOS"
|
|
16
|
+
echo " apt install gh # Linux"
|
|
17
|
+
exit 1
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Check if authenticated
|
|
21
|
+
if ! gh auth status &> /dev/null; then
|
|
22
|
+
echo "Error: Not authenticated with GitHub CLI."
|
|
23
|
+
echo "Run: gh auth login"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# Set branch protection
|
|
28
|
+
echo "Configuring branch protection rules..."
|
|
29
|
+
|
|
30
|
+
# Create temporary JSON file for the protection payload
|
|
31
|
+
# After first CI run, update the "contexts" array with actual check names
|
|
32
|
+
# Example: "contexts": ["Test (Python 3.11)", "Test (Python 3.12)", "Lint"]
|
|
33
|
+
TMP_FILE=$(mktemp)
|
|
34
|
+
cat > "$TMP_FILE" <<EOF
|
|
35
|
+
{
|
|
36
|
+
"required_status_checks": {
|
|
37
|
+
"strict": true,
|
|
38
|
+
"contexts": []
|
|
39
|
+
},
|
|
40
|
+
"enforce_admins": true,
|
|
41
|
+
"required_pull_request_reviews": {
|
|
42
|
+
"required_approving_review_count": 1,
|
|
43
|
+
"dismiss_stale_reviews": true,
|
|
44
|
+
"require_code_owner_reviews": false,
|
|
45
|
+
"require_last_push_approval": false
|
|
46
|
+
},
|
|
47
|
+
"restrictions": null,
|
|
48
|
+
"allow_force_pushes": false,
|
|
49
|
+
"allow_deletions": false,
|
|
50
|
+
"required_linear_history": false,
|
|
51
|
+
"required_conversation_resolution": true,
|
|
52
|
+
"allow_squash_merge": true,
|
|
53
|
+
"allow_merge_commit": true,
|
|
54
|
+
"allow_rebase_merge": true
|
|
55
|
+
}
|
|
56
|
+
EOF
|
|
57
|
+
|
|
58
|
+
gh api "repos/${REPO_OWNER}/${REPO_NAME}/branches/${BRANCH}/protection" \
|
|
59
|
+
--method PUT \
|
|
60
|
+
--input "$TMP_FILE"
|
|
61
|
+
|
|
62
|
+
# Clean up
|
|
63
|
+
rm "$TMP_FILE"
|
|
64
|
+
|
|
65
|
+
echo "✅ Branch protection configured successfully!"
|
|
66
|
+
echo ""
|
|
67
|
+
echo "Branch protection rules:"
|
|
68
|
+
echo " - Require pull request reviews (1 approval, author can merge own PRs)"
|
|
69
|
+
echo " - Require conversation resolution before merging"
|
|
70
|
+
echo " - Require status checks to pass"
|
|
71
|
+
echo " - Require branches to be up to date"
|
|
72
|
+
echo " - Enforce admins"
|
|
73
|
+
echo " - Disallow force pushes"
|
|
74
|
+
echo " - Disallow deletions"
|
|
75
|
+
echo ""
|
|
76
|
+
echo ""
|
|
77
|
+
echo "⚠️ Important: Status checks are currently set to an empty list."
|
|
78
|
+
echo " After the first CI run completes:"
|
|
79
|
+
echo " 1. Go to any PR or commit and check the 'Checks' tab"
|
|
80
|
+
echo " 2. Note the exact status check names (e.g., 'Test (Python 3.11)', 'Lint')"
|
|
81
|
+
echo " 3. Update branch protection via GitHub web interface:"
|
|
82
|
+
echo " Settings → Branches → Edit rule for 'main'"
|
|
83
|
+
echo " → Add the status checks under 'Require status checks to pass'"
|
|
84
|
+
echo ""
|
|
85
|
+
echo " Or update this script with the correct context names and run it again."
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- '**' # Run on all branches
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
- master
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Test (Python ${{ matrix.python-version }})
|
|
15
|
+
runs-on: ${{ matrix.os }}
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
os: [ubuntu-latest, macos-latest]
|
|
20
|
+
python-version: ['3.11', '3.12', '3.13']
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- name: Checkout code
|
|
24
|
+
uses: actions/checkout@v4
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
uses: astral-sh/setup-uv@v4
|
|
28
|
+
with:
|
|
29
|
+
version: "latest"
|
|
30
|
+
|
|
31
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
32
|
+
uses: actions/setup-python@v5
|
|
33
|
+
with:
|
|
34
|
+
python-version: ${{ matrix.python-version }}
|
|
35
|
+
|
|
36
|
+
- name: Install dependencies
|
|
37
|
+
run: uv sync --extra dev
|
|
38
|
+
|
|
39
|
+
- name: Run tests
|
|
40
|
+
run: uv run pytest
|
|
41
|
+
|
|
42
|
+
lint:
|
|
43
|
+
name: Lint
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
|
|
46
|
+
steps:
|
|
47
|
+
- name: Checkout code
|
|
48
|
+
uses: actions/checkout@v4
|
|
49
|
+
|
|
50
|
+
- name: Install uv
|
|
51
|
+
uses: astral-sh/setup-uv@v4
|
|
52
|
+
with:
|
|
53
|
+
version: "latest"
|
|
54
|
+
|
|
55
|
+
- name: Set up Python
|
|
56
|
+
uses: actions/setup-python@v5
|
|
57
|
+
with:
|
|
58
|
+
python-version: '3.11'
|
|
59
|
+
|
|
60
|
+
- name: Install dependencies
|
|
61
|
+
run: uv sync --extra dev
|
|
62
|
+
|
|
63
|
+
- name: Run mypy
|
|
64
|
+
run: uv run mypy src/gww
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v[0-9]+.[0-9]+.[0-9]+'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
name: Publish release
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment: pypi
|
|
13
|
+
permissions:
|
|
14
|
+
id-token: write
|
|
15
|
+
contents: write
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
with:
|
|
21
|
+
fetch-depth: 0
|
|
22
|
+
|
|
23
|
+
- name: Verify tag and extract version
|
|
24
|
+
id: version
|
|
25
|
+
run: |
|
|
26
|
+
TAG="${GITHUB_REF_NAME}"
|
|
27
|
+
if ! [[ "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
28
|
+
echo "::error::Tag '${TAG}' is not strict SemVer (vX.Y.Z). Pre-release tags are not supported."
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
VERSION="${TAG#v}"
|
|
32
|
+
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
|
|
33
|
+
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
|
|
34
|
+
|
|
35
|
+
- name: Verify pyproject.toml version matches tag
|
|
36
|
+
run: |
|
|
37
|
+
PYPROJECT_VERSION=$(grep -E '^version[[:space:]]*=' pyproject.toml | head -1 | sed -E 's/.*"([^"]+)".*/\1/')
|
|
38
|
+
if [ -z "$PYPROJECT_VERSION" ]; then
|
|
39
|
+
echo "::error::Could not extract version from pyproject.toml"
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
if [ "$PYPROJECT_VERSION" != "${{ steps.version.outputs.version }}" ]; then
|
|
43
|
+
echo "::error::pyproject.toml version '${PYPROJECT_VERSION}' does not match tag '${{ steps.version.outputs.version }}'"
|
|
44
|
+
exit 1
|
|
45
|
+
fi
|
|
46
|
+
echo "Version match: ${PYPROJECT_VERSION}"
|
|
47
|
+
|
|
48
|
+
- name: Install uv
|
|
49
|
+
uses: astral-sh/setup-uv@v4
|
|
50
|
+
with:
|
|
51
|
+
version: "latest"
|
|
52
|
+
|
|
53
|
+
- name: Set up Python
|
|
54
|
+
uses: actions/setup-python@v5
|
|
55
|
+
with:
|
|
56
|
+
python-version: '3.12'
|
|
57
|
+
|
|
58
|
+
- name: Build sdist and wheel
|
|
59
|
+
run: uv build
|
|
60
|
+
|
|
61
|
+
- name: Publish to PyPI
|
|
62
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
63
|
+
|
|
64
|
+
- name: Create GitHub Release
|
|
65
|
+
uses: softprops/action-gh-release@v2
|
|
66
|
+
with:
|
|
67
|
+
tag_name: ${{ steps.version.outputs.tag }}
|
|
68
|
+
name: ${{ steps.version.outputs.tag }}
|
|
69
|
+
generate_release_notes: true
|
|
70
|
+
files: |
|
|
71
|
+
dist/*.tar.gz
|
|
72
|
+
dist/*.whl
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
|
|
8
|
+
# Virtual environments
|
|
9
|
+
.venv/
|
|
10
|
+
|
|
11
|
+
# Testing
|
|
12
|
+
.pytest_cache/
|
|
13
|
+
.coverage
|
|
14
|
+
htmlcov/
|
|
15
|
+
|
|
16
|
+
# Type checking
|
|
17
|
+
.mypy_cache/
|
|
18
|
+
|
|
19
|
+
# IDE
|
|
20
|
+
.idea/
|
|
21
|
+
*.swp
|
|
22
|
+
*~
|
|
23
|
+
|
|
24
|
+
# OS
|
|
25
|
+
.DS_Store
|
|
26
|
+
Thumbs.db
|
|
27
|
+
Desktop.ini
|
|
28
|
+
|
|
29
|
+
# Environment
|
|
30
|
+
.env
|
|
31
|
+
.env.*
|
|
32
|
+
|
|
33
|
+
# Local notes
|
|
34
|
+
TODO.md
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sync-docs-en-to-ru
|
|
3
|
+
description: Sync English documentation (README.md) to Russian documentation (README.ru.md), preserving Russian language while updating structure and content. Use when the user asks to sync, update, or align README.ru.md with README.md (or asks to translate/retranslate docs from English to Russian).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Sync English docs to Russian docs
|
|
7
|
+
|
|
8
|
+
Synchronize the English documentation (`README.md`) to the Russian documentation (`README.ru.md`):
|
|
9
|
+
- Preserve the Russian language in the output
|
|
10
|
+
- Update structure to match the English version if it's more complete
|
|
11
|
+
- Add missing sections from the English version
|
|
12
|
+
- Ensure both documents have the same structure and content coverage
|
|
13
|
+
- Maintain proper markdown formatting
|
|
14
|
+
|
|
15
|
+
## User input
|
|
16
|
+
|
|
17
|
+
The user may provide optional context in their message (for example: "sync only the Installation section", "focus on template functions", or "leave the Contributing section alone"). If they do, honor it. If they don't, perform a full sync.
|
|
18
|
+
|
|
19
|
+
## Workflow
|
|
20
|
+
|
|
21
|
+
### 1. Load both documentation files
|
|
22
|
+
|
|
23
|
+
Read both files from the project root:
|
|
24
|
+
- `README.md` (English — source of truth for structure and content)
|
|
25
|
+
- `README.ru.md` (Russian — target file to update)
|
|
26
|
+
|
|
27
|
+
### 2. Analyze structure
|
|
28
|
+
|
|
29
|
+
Compare the structure of both files:
|
|
30
|
+
- Extract all headings (H1, H2, H3, etc.) from both files
|
|
31
|
+
- Identify sections present in English but missing in Russian
|
|
32
|
+
- Identify sections present in Russian but missing in English
|
|
33
|
+
- Note any structural differences (order, nesting, etc.)
|
|
34
|
+
|
|
35
|
+
### 3. Content comparison
|
|
36
|
+
|
|
37
|
+
For each section:
|
|
38
|
+
- Compare content coverage (not exact text, but topics covered)
|
|
39
|
+
- Identify missing information in Russian version
|
|
40
|
+
- Note any differences in examples, code blocks, or explanations
|
|
41
|
+
- Check if English version has updated or new content
|
|
42
|
+
|
|
43
|
+
### 4. Sync `README.ru.md` to match `README.md`
|
|
44
|
+
|
|
45
|
+
1. **Preserve Russian language** — All prose must remain in Russian. Do NOT paste English text directly. Instead:
|
|
46
|
+
- Use existing Russian text where it exists and matches the English meaning
|
|
47
|
+
- For new sections, translate English content to Russian
|
|
48
|
+
- For updated sections, update Russian text to match English meaning
|
|
49
|
+
- Maintain the same tone and style as the existing Russian documentation
|
|
50
|
+
|
|
51
|
+
2. **Structure alignment**:
|
|
52
|
+
- Add missing sections from the English version (translated to Russian)
|
|
53
|
+
- Reorder sections if the English version has better organization
|
|
54
|
+
- Ensure heading levels match
|
|
55
|
+
- Remove sections that no longer exist in the English version
|
|
56
|
+
|
|
57
|
+
3. **Content updates**:
|
|
58
|
+
- Add missing code examples, tables, or explanations (translate descriptions to Russian, keep code/examples as-is)
|
|
59
|
+
- Update existing sections if English version has more complete information
|
|
60
|
+
- Preserve all examples and code blocks (code stays in English, comments/descriptions translated)
|
|
61
|
+
- Translate any new English text to Russian
|
|
62
|
+
|
|
63
|
+
4. **Language switcher** — Ensure the language switcher at the top is correct:
|
|
64
|
+
- Russian version: `[English](README.md) | **Русский**`
|
|
65
|
+
- Preserve this format
|
|
66
|
+
|
|
67
|
+
5. **Preserve formatting**:
|
|
68
|
+
- Maintain emoji usage consistency
|
|
69
|
+
- Preserve code block formatting
|
|
70
|
+
- Keep table structures (translate table headers and content to Russian)
|
|
71
|
+
- Maintain list formatting
|
|
72
|
+
|
|
73
|
+
6. **Translation guidelines**:
|
|
74
|
+
- Translate all descriptive text to Russian
|
|
75
|
+
- Keep code examples, commands, and technical terms in English (as they appear in Russian version)
|
|
76
|
+
- Translate table headers and descriptions
|
|
77
|
+
- Translate section headings
|
|
78
|
+
- Maintain technical accuracy in translation
|
|
79
|
+
|
|
80
|
+
### 5. Validate
|
|
81
|
+
|
|
82
|
+
After updating, verify:
|
|
83
|
+
- All sections from English version are present in Russian
|
|
84
|
+
- Structure matches between both files
|
|
85
|
+
- No English descriptive text remains in Russian file (code is OK)
|
|
86
|
+
- Markdown formatting is correct
|
|
87
|
+
- Language switcher is present and correct
|
|
88
|
+
- All new content is properly translated
|
|
89
|
+
|
|
90
|
+
### 6. Report changes
|
|
91
|
+
|
|
92
|
+
Provide a summary of:
|
|
93
|
+
- Sections added (with Russian translations)
|
|
94
|
+
- Sections updated
|
|
95
|
+
- Structural changes made
|
|
96
|
+
- Translation notes (if any terms needed clarification)
|
|
97
|
+
- Any notes about content that couldn't be automatically synced
|
|
98
|
+
|
|
99
|
+
## Operating principles
|
|
100
|
+
|
|
101
|
+
- **Read-only on English file** — Never modify `README.md`
|
|
102
|
+
- **Russian-first** — Always write/update content in Russian
|
|
103
|
+
- **Structure preservation** — Match the English structure exactly
|
|
104
|
+
- **Content completeness** — Ensure Russian version has all information from English version
|
|
105
|
+
- **Formatting consistency** — Maintain consistent markdown formatting
|
|
106
|
+
- **Translation quality** — Provide accurate Russian translations that maintain technical accuracy
|
|
107
|
+
|
|
108
|
+
## Notes
|
|
109
|
+
|
|
110
|
+
- If the English version has content that doesn't exist in Russian, translate it to Russian
|
|
111
|
+
- If there are discrepancies, prefer the English version as the source of truth for structure and content
|
|
112
|
+
- Preserve any Russian-specific improvements that don't exist in English version (but note them in the report)
|
|
113
|
+
- Code blocks, commands, and technical identifiers should remain in English
|
|
114
|
+
- Translate all user-facing text, descriptions, and explanations to Russian
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|