Skip to content

Commit 2711ab0

Browse files
committed
feat: Add comprehensive installer infrastructure
- Fix setup.py placeholder values and dependency issues - Add modern pyproject.toml build configuration - Create PyInstaller-compatible standalone entry point - Fix CI/CD workflows for implementations/python/ structure - Add cross-platform installer workflow with GitHub Actions - Support Windows, macOS, Linux executable generation - Include professional install scripts with PATH integration Resolves installer creation and distribution capabilities.
1 parent 1a8cd86 commit 2711ab0

7 files changed

Lines changed: 413 additions & 8 deletions

File tree

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
name: Build Installers
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*'
7+
workflow_dispatch:
8+
9+
jobs:
10+
build-python-executable:
11+
strategy:
12+
matrix:
13+
os: [ubuntu-latest, windows-latest, macos-latest]
14+
include:
15+
- os: ubuntu-latest
16+
executable_name: cfgpp
17+
artifact_name: cfgpp-linux-x64
18+
- os: windows-latest
19+
executable_name: cfgpp.exe
20+
artifact_name: cfgpp-windows-x64
21+
- os: macos-latest
22+
executable_name: cfgpp
23+
artifact_name: cfgpp-macos-x64
24+
25+
runs-on: ${{ matrix.os }}
26+
27+
steps:
28+
- uses: actions/checkout@v4
29+
30+
- name: Set up Python 3.9
31+
uses: actions/setup-python@v4
32+
with:
33+
python-version: 3.9
34+
35+
- name: Install dependencies
36+
run: |
37+
python -m pip install --upgrade pip
38+
pip install pyinstaller
39+
cd implementations/python
40+
pip install -e .
41+
42+
- name: Build executable with PyInstaller
43+
run: |
44+
cd implementations/python
45+
if [ "${{ matrix.os }}" == "windows-latest" ]; then
46+
pyinstaller --onefile --name cfgpp --console src/cfgpp_standalone.py
47+
else
48+
pyinstaller --onefile --name cfgpp --console src/cfgpp_standalone.py
49+
fi
50+
shell: bash
51+
52+
- name: Test executable
53+
run: |
54+
cd implementations/python/dist
55+
if [ "${{ matrix.os }}" == "windows-latest" ]; then
56+
./cfgpp.exe --help
57+
else
58+
./cfgpp --help
59+
fi
60+
shell: bash
61+
62+
- name: Create installer package
63+
run: |
64+
cd implementations/python
65+
mkdir -p installer
66+
# Copy executable
67+
if [ "${{ matrix.os }}" == "windows-latest" ]; then
68+
cp dist/cfgpp.exe installer/
69+
else
70+
cp dist/cfgpp installer/
71+
fi
72+
cp README.md installer/
73+
cp ../../LICENSE installer/ || echo "No LICENSE file found"
74+
75+
# Create install script for Unix systems
76+
if [ "${{ matrix.os }}" != "windows-latest" ]; then
77+
cat > installer/install.sh << 'EOF'
78+
#!/bin/bash
79+
# CFGPP Installer Script
80+
81+
INSTALL_DIR="$HOME/.local/bin"
82+
EXECUTABLE_NAME="cfgpp"
83+
84+
echo "Installing CFGPP Configuration Parser..."
85+
86+
# Create install directory if it doesn't exist
87+
mkdir -p "$INSTALL_DIR"
88+
89+
# Copy executable
90+
cp "$EXECUTABLE_NAME" "$INSTALL_DIR/"
91+
chmod +x "$INSTALL_DIR/$EXECUTABLE_NAME"
92+
93+
echo "CFGPP installed to $INSTALL_DIR/$EXECUTABLE_NAME"
94+
echo ""
95+
echo "Add $INSTALL_DIR to your PATH if not already present:"
96+
echo " export PATH=\"\$PATH:$INSTALL_DIR\""
97+
echo ""
98+
echo "Test installation:"
99+
echo " cfgpp --help"
100+
EOF
101+
chmod +x installer/install.sh
102+
fi
103+
104+
# Create install script for Windows
105+
if [ "${{ matrix.os }}" == "windows-latest" ]; then
106+
cat > installer/install.bat << 'EOF'
107+
@echo off
108+
REM CFGPP Installer Script for Windows
109+
110+
set "INSTALL_DIR=%LOCALAPPDATA%\cfgpp"
111+
set "EXECUTABLE_NAME=cfgpp.exe"
112+
113+
echo Installing CFGPP Configuration Parser...
114+
115+
REM Create install directory
116+
if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%"
117+
118+
REM Copy executable
119+
copy "%EXECUTABLE_NAME%" "%INSTALL_DIR%\"
120+
121+
echo CFGPP installed to %INSTALL_DIR%\%EXECUTABLE_NAME%
122+
echo.
123+
echo Add %INSTALL_DIR% to your PATH environment variable
124+
echo Test installation: cfgpp --help
125+
126+
pause
127+
EOF
128+
fi
129+
shell: bash
130+
131+
- name: Create archive
132+
run: |
133+
cd implementations/python/installer
134+
if [ "${{ matrix.os }}" == "windows-latest" ]; then
135+
7z a ../${{ matrix.artifact_name }}.zip *
136+
else
137+
tar -czf ../${{ matrix.artifact_name }}.tar.gz *
138+
fi
139+
shell: bash
140+
141+
- name: Upload installer artifacts
142+
uses: actions/upload-artifact@v3
143+
with:
144+
name: ${{ matrix.artifact_name }}
145+
path: |
146+
implementations/python/${{ matrix.artifact_name }}.zip
147+
implementations/python/${{ matrix.artifact_name }}.tar.gz
148+
149+
create-release:
150+
needs: build-python-executable
151+
runs-on: ubuntu-latest
152+
if: startsWith(github.ref, 'refs/tags/v')
153+
154+
steps:
155+
- uses: actions/checkout@v4
156+
157+
- name: Download all artifacts
158+
uses: actions/download-artifact@v3
159+
160+
- name: Generate release notes
161+
run: |
162+
VERSION=${GITHUB_REF#refs/tags/v}
163+
echo "VERSION=$VERSION" >> $GITHUB_ENV
164+
165+
cat > RELEASE_NOTES.md << EOF
166+
# CFGPP v$VERSION - Configuration Parser & Tools
167+
168+
## Installation Options
169+
170+
### Option 1: Python Package (Recommended)
171+
\`\`\`bash
172+
pip install cfgpp
173+
\`\`\`
174+
175+
### Option 2: Standalone Executables
176+
Download the appropriate executable for your platform:
177+
178+
- **Windows**: cfgpp-windows-x64.zip
179+
- **macOS**: cfgpp-macos-x64.tar.gz
180+
- **Linux**: cfgpp-linux-x64.tar.gz
181+
182+
Extract and run the included install script, or manually place the executable in your PATH.
183+
184+
## Usage
185+
\`\`\`bash
186+
cfgpp --help # Show help
187+
cfgpp parse config.cfgpp # Parse configuration file
188+
cfgpp validate config.cfgpp # Validate syntax
189+
cfgpp format config.cfgpp # Format configuration
190+
\`\`\`
191+
192+
## Features
193+
- Robust bracket-based syntax (no indentation sensitivity)
194+
- Environment variable interpolation: \${VAR:-default}
195+
- Include/import functionality with circular detection
196+
- Expression evaluation and string operations
197+
- Cross-platform CLI tools
198+
199+
## Changes in this Release
200+
EOF
201+
202+
# Get commits since last tag
203+
LAST_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
204+
if [ -n "$LAST_TAG" ]; then
205+
git log --pretty=format:"- %s" $LAST_TAG..HEAD >> RELEASE_NOTES.md
206+
else
207+
echo "- Initial release with comprehensive installer support" >> RELEASE_NOTES.md
208+
fi
209+
210+
- name: Create GitHub Release
211+
uses: actions/create-release@v1
212+
id: create_release
213+
env:
214+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
215+
with:
216+
tag_name: ${{ github.ref }}
217+
release_name: CFGPP v${{ env.VERSION }}
218+
body_path: RELEASE_NOTES.md
219+
draft: false
220+
prerelease: false
221+
222+
- name: Upload Release Assets
223+
run: |
224+
# Find and upload all installer archives
225+
find . -name "*.zip" -o -name "*.tar.gz" | while read file; do
226+
if [[ -f "$file" ]]; then
227+
filename=$(basename "$file")
228+
echo "Uploading $filename..."
229+
curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
230+
-H "Content-Type: application/octet-stream" \
231+
--data-binary @"$file" \
232+
"${{ steps.create_release.outputs.upload_url }}?name=$filename"
233+
fi
234+
done

.github/workflows/ci.yml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,20 @@ jobs:
3636
uses: actions/cache@v3
3737
with:
3838
path: ~/.cache/pip
39-
key: ${{ runner.os }}-pip-${{ hashFiles('**/setup.py') }}
39+
key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml', '**/requirements.txt') }}
4040
restore-keys: |
4141
${{ runner.os }}-pip-
4242
4343
- name: Install dependencies
4444
run: |
4545
python -m pip install --upgrade pip
46+
cd implementations/python
4647
pip install -e .
4748
pip install pytest pytest-cov pytest-xdist
4849
4950
- name: Run tests
5051
run: |
52+
cd implementations/python
5153
pytest --cov=src/cfgpp --cov-report=xml --cov-report=term-missing -v
5254
5355
- name: Upload coverage to Codecov
@@ -73,19 +75,23 @@ jobs:
7375
run: |
7476
python -m pip install --upgrade pip
7577
pip install black flake8 mypy
78+
cd implementations/python
7679
pip install -e .
7780
7881
- name: Check code formatting with Black
7982
run: |
83+
cd implementations/python
8084
black --check --diff src/ tests/
8185
8286
- name: Lint with flake8
8387
run: |
88+
cd implementations/python
8489
flake8 src/ tests/ --count --select=E9,F63,F7,F82 --show-source --statistics
8590
flake8 src/ tests/ --count --exit-zero --max-complexity=10 --max-line-length=88 --statistics
8691
8792
- name: Type check with mypy
8893
run: |
94+
cd implementations/python
8995
mypy src/ --ignore-missing-imports
9096
9197
security:
@@ -102,10 +108,12 @@ jobs:
102108
run: |
103109
python -m pip install --upgrade pip
104110
pip install bandit safety
111+
cd implementations/python
105112
pip install -e .
106113
107114
- name: Run security checks with bandit
108115
run: |
116+
cd implementations/python
109117
bandit -r src/ -f json -o bandit-report.json || true
110118
bandit -r src/
111119
@@ -126,6 +134,7 @@ jobs:
126134
- name: Install dependencies
127135
run: |
128136
python -m pip install --upgrade pip
137+
cd implementations/python
129138
pip install -e .
130139
131140
- name: Validate documentation links
@@ -181,6 +190,7 @@ jobs:
181190
- name: Install dependencies
182191
run: |
183192
python -m pip install --upgrade pip
193+
cd implementations/python
184194
pip install -e .
185195
186196
- name: Run integration tests
@@ -267,18 +277,21 @@ jobs:
267277
run: |
268278
python -m pip install --upgrade pip
269279
pip install build twine
280+
cd implementations/python
270281
pip install -e .
271282
272283
- name: Build package
273284
run: |
285+
cd implementations/python
274286
python -m build
275287
276288
- name: Check package
277289
run: |
290+
cd implementations/python
278291
twine check dist/*
279292
280293
- name: Upload build artifacts
281294
uses: actions/upload-artifact@v3
282295
with:
283296
name: dist
284-
path: dist/
297+
path: implementations/python/dist/

.github/workflows/release.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,17 @@ jobs:
2222
run: |
2323
python -m pip install --upgrade pip
2424
pip install build twine
25+
cd implementations/python
2526
pip install -e .
2627
2728
- name: Build package
2829
run: |
30+
cd implementations/python
2931
python -m build
3032
3133
- name: Check package
3234
run: |
35+
cd implementations/python
3336
twine check dist/*
3437
3538
- name: Generate changelog
@@ -66,7 +69,7 @@ jobs:
6669
uses: actions/upload-artifact@v3
6770
with:
6871
name: dist-${{ env.VERSION }}
69-
path: dist/
72+
path: implementations/python/dist/
7073

7174
# Uncomment when ready to publish to PyPI
7275
# - name: Publish to PyPI

implementations/python/cfgpp.spec

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# -*- mode: python ; coding: utf-8 -*-
2+
3+
4+
a = Analysis(
5+
['src\\cfgpp_standalone.py'],
6+
pathex=[],
7+
binaries=[],
8+
datas=[],
9+
hiddenimports=[],
10+
hookspath=[],
11+
hooksconfig={},
12+
runtime_hooks=[],
13+
excludes=[],
14+
noarchive=False,
15+
optimize=0,
16+
)
17+
pyz = PYZ(a.pure)
18+
19+
exe = EXE(
20+
pyz,
21+
a.scripts,
22+
a.binaries,
23+
a.datas,
24+
[],
25+
name='cfgpp',
26+
debug=False,
27+
bootloader_ignore_signals=False,
28+
strip=False,
29+
upx=True,
30+
upx_exclude=[],
31+
runtime_tmpdir=None,
32+
console=True,
33+
disable_windowed_traceback=False,
34+
argv_emulation=False,
35+
target_arch=None,
36+
codesign_identity=None,
37+
entitlements_file=None,
38+
)

0 commit comments

Comments
 (0)