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
0 commit comments