Refactor source code archive creation in GitHub workflow for improved… #24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Build and Release Flex | |
on: | |
push: | |
branches: [ main, master ] | |
tags: | |
- 'v*' # Run when tag is pushed (for versioned releases) | |
jobs: | |
build: | |
name: Build Flex for ${{ matrix.os }} | |
runs-on: ${{ matrix.os }} | |
strategy: | |
fail-fast: false | |
matrix: | |
os: [ubuntu-latest, windows-latest, macos-latest] | |
include: | |
- os: ubuntu-latest | |
output_name: flex | |
asset_name: flex-linux | |
- os: windows-latest | |
output_name: flex.exe | |
asset_name: flex-windows | |
- os: macos-latest | |
output_name: flex | |
asset_name: flex-macos | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Set up Python | |
uses: actions/setup-python@v4 | |
with: | |
python-version: '3.10' | |
- name: Get version information | |
id: version | |
run: | | |
if [[ $GITHUB_REF == refs/tags/v* ]]; then | |
VERSION=${GITHUB_REF#refs/tags/v} | |
else | |
VERSION="dev-$(date +'%Y%m%d')-${GITHUB_SHA::7}" | |
fi | |
echo "VERSION=$VERSION" >> $GITHUB_ENV | |
echo "version=$VERSION" >> $GITHUB_OUTPUT | |
shell: bash | |
- name: Install dependencies | |
run: | | |
python -m pip install --upgrade pip | |
pip install pyinstaller | |
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi | |
shell: bash | |
- name: Run tests | |
run: | | |
cd src | |
python -m unittest discover -s flex_tester | |
shell: bash | |
- name: Build executable with PyInstaller | |
run: | | |
cd src | |
pyinstaller --onefile main.py -n flex | |
shell: bash | |
# Windows NSIS Installer | |
- name: Create Windows Installer | |
if: runner.os == 'Windows' | |
run: | | |
choco install nsis -y | |
mkdir -p installer | |
copy src\dist\flex.exe installer\ | |
xcopy src\flex_tester installer\examples\ /E /I | |
copy README.md installer\ | |
# Create a simple NSIS script file | |
( | |
echo !include "MUI2.nsh" | |
echo Name "Flex Programming Language" | |
echo OutFile "flex-${{ env.VERSION }}-win.exe" | |
echo InstallDir "$PROGRAMFILES\Flex" | |
echo RequestExecutionLevel admin | |
echo !insertmacro MUI_PAGE_WELCOME | |
echo !insertmacro MUI_PAGE_DIRECTORY | |
echo !insertmacro MUI_PAGE_INSTFILES | |
echo !insertmacro MUI_PAGE_FINISH | |
echo !insertmacro MUI_LANGUAGE "English" | |
echo Section | |
echo SetOutPath "$INSTDIR" | |
echo File /r "installer\*.*" | |
echo WriteUninstaller "$INSTDIR\uninstall.exe" | |
echo CreateDirectory "$SMPROGRAMS\Flex" | |
echo CreateShortcut "$SMPROGRAMS\Flex\Flex.lnk" "$INSTDIR\flex.exe" | |
echo CreateShortcut "$SMPROGRAMS\Flex\Uninstall.lnk" "$INSTDIR\uninstall.exe" | |
echo SectionEnd | |
echo Section "Uninstall" | |
echo Delete "$INSTDIR\uninstall.exe" | |
echo RMDir /r "$INSTDIR" | |
echo RMDir /r "$SMPROGRAMS\Flex" | |
echo SectionEnd | |
) > installer.nsi | |
REM Compile the installer | |
makensis installer.nsi | |
REM Create latest.yml for auto-updater compatibility | |
echo version: ${{ env.VERSION }} > latest-win.yml | |
echo files: >> latest-win.yml | |
echo - url: flex-${{ env.VERSION }}-win.exe >> latest-win.yml | |
FOR /F "tokens=*" %%a IN ('powershell -Command "(Get-FileHash -Algorithm SHA512 flex-${{ env.VERSION }}-win.exe).Hash.ToLower()"') DO SET FILEHASH=%%a | |
echo sha512: %FILEHASH% >> latest-win.yml | |
echo path: flex-${{ env.VERSION }}-win.exe >> latest-win.yml | |
FOR /F "tokens=*" %%a IN ('powershell -Command "(Get-FileHash -Algorithm SHA512 flex-${{ env.VERSION }}-win.exe).Hash.ToLower()"') DO SET FILEHASH=%%a | |
echo sha512: %FILEHASH% >> latest-win.yml | |
shell: cmd | |
# macOS DMG Package | |
- name: Create macOS DMG | |
if: runner.os == 'macOS' | |
run: | | |
# Install create-dmg | |
brew install create-dmg | |
# Create app bundle structure | |
mkdir -p Flex.app/Contents/{MacOS,Resources} | |
cp src/dist/flex Flex.app/Contents/MacOS/ | |
cp -r src/flex_tester Flex.app/Contents/Resources/examples | |
cp README.md Flex.app/Contents/Resources/ | |
# Create Info.plist | |
cat > Flex.app/Contents/Info.plist << EOF | |
<?xml version="1.0" encoding="UTF-8"?> | |
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
<plist version="1.0"> | |
<dict> | |
<key>CFBundleExecutable</key> | |
<string>flex</string> | |
<key>CFBundleIconFile</key> | |
<string>flex.icns</string> | |
<key>CFBundleIdentifier</key> | |
<string>org.flex-lang.flex</string> | |
<key>CFBundleName</key> | |
<string>Flex</string> | |
<key>CFBundlePackageType</key> | |
<string>APPL</string> | |
<key>CFBundleVersion</key> | |
<string>${VERSION}</string> | |
<key>NSHighResolutionCapable</key> | |
<true/> | |
</dict> | |
</plist> | |
EOF | |
# Create DMG with basic settings | |
create-dmg \ | |
--volname "Flex Installer" \ | |
--window-pos 200 120 \ | |
--window-size 800 400 \ | |
--icon-size 100 \ | |
--icon "Flex.app" 200 190 \ | |
--hide-extension "Flex.app" \ | |
--app-drop-link 600 185 \ | |
"flex-${VERSION}-mac.dmg" \ | |
"Flex.app" | |
# Create latest-mac.yml for auto-updater compatibility | |
echo "version: ${VERSION}" > latest-mac.yml | |
echo "files:" >> latest-mac.yml | |
echo " - url: flex-${VERSION}-mac.dmg" >> latest-mac.yml | |
echo " sha512: $(shasum -a 512 flex-${VERSION}-mac.dmg | awk '{print $1}')" >> latest-mac.yml | |
echo " size: $(stat -f%z flex-${VERSION}-mac.dmg)" >> latest-mac.yml | |
echo "path: flex-${VERSION}-mac.dmg" >> latest-mac.yml | |
echo "sha512: $(shasum -a 512 flex-${VERSION}-mac.dmg | awk '{print $1}')" >> latest-mac.yml | |
echo "size: $(stat -f%z flex-${VERSION}-mac.dmg)" >> latest-mac.yml | |
shell: bash | |
continue-on-error: true # DMG creation might fail if dependencies are missing | |
# Linux AppImage | |
- name: Create Linux AppImage and Deb | |
if: runner.os == 'Linux' | |
run: | | |
# Install required tools | |
sudo apt-get update | |
sudo apt-get install -y wget fuse libfuse2 dpkg-dev | |
# Download AppImage tools | |
wget -q https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage -O appimagetool | |
chmod +x appimagetool | |
# Create AppDir structure | |
mkdir -p AppDir/usr/{bin,share/applications,share/icons/hicolor/256x256/apps,share/flex/examples} | |
cp src/dist/flex AppDir/usr/bin/ | |
cp -r src/flex_tester/* AppDir/usr/share/flex/examples/ | |
cp README.md AppDir/usr/share/flex/ | |
# Create desktop file | |
cat > AppDir/usr/share/applications/flex.desktop << EOF | |
[Desktop Entry] | |
Name=Flex | |
Comment=Flex Programming Language | |
Exec=flex | |
Icon=flex | |
Type=Application | |
Categories=Development; | |
Terminal=true | |
EOF | |
# Copy desktop file to root (required by AppImage) | |
cp AppDir/usr/share/applications/flex.desktop AppDir/ | |
# Create AppRun script | |
cat > AppDir/AppRun << EOF | |
#!/bin/sh | |
SELF=\$(readlink -f "\$0") | |
HERE=\${SELF%/*} | |
export PATH="\${HERE}/usr/bin:\${PATH}" | |
exec "\${HERE}/usr/bin/flex" "\$@" | |
EOF | |
chmod +x AppDir/AppRun | |
# Create AppImage | |
ARCH=x86_64 ./appimagetool AppDir flex-${VERSION}-linux.AppImage | |
# Create Debian package | |
mkdir -p flex-deb/DEBIAN | |
mkdir -p flex-deb/usr/bin | |
mkdir -p flex-deb/usr/share/flex/examples | |
mkdir -p flex-deb/usr/share/applications | |
cp src/dist/flex flex-deb/usr/bin/ | |
cp -r src/flex_tester/* flex-deb/usr/share/flex/examples/ | |
cp AppDir/usr/share/applications/flex.desktop flex-deb/usr/share/applications/ | |
cat > flex-deb/DEBIAN/control << EOF | |
Package: flex | |
Version: ${VERSION} | |
Section: development | |
Priority: optional | |
Architecture: amd64 | |
Maintainer: Flex Language Team <info@flex-lang.org> | |
Description: Flex Programming Language | |
A modern and flexible programming language. | |
EOF | |
dpkg-deb --build flex-deb flex-${VERSION}-linux.deb | |
# Create latest-linux.yml for auto-updater compatibility | |
echo "version: ${VERSION}" > latest-linux.yml | |
echo "files:" >> latest-linux.yml | |
echo " - url: flex-${VERSION}-linux.AppImage" >> latest-linux.yml | |
echo " sha512: $(sha512sum flex-${VERSION}-linux.AppImage | awk '{print $1}')" >> latest-linux.yml | |
echo " size: $(stat -c%s flex-${VERSION}-linux.AppImage)" >> latest-linux.yml | |
echo "path: flex-${VERSION}-linux.AppImage" >> latest-linux.yml | |
echo "sha512: $(sha512sum flex-${VERSION}-linux.AppImage | awk '{print $1}')" >> latest-linux.yml | |
echo "size: $(stat -c%s flex-${VERSION}-linux.AppImage)" >> latest-linux.yml | |
shell: bash | |
continue-on-error: true # Some parts might fail if dependencies are missing | |
# Package distribution (Unix) - keep this as backup for Linux/macOS | |
- name: Package distribution (Unix) | |
if: runner.os != 'Windows' | |
run: | | |
mkdir -p dist/flex | |
cp src/dist/flex dist/flex/ | |
cp -r src/flex_tester dist/flex/examples | |
cp README.md dist/flex/ | |
tar -czf flex-${VERSION}-${{ matrix.asset_name }}.tar.gz -C dist flex | |
shell: bash | |
# Package distribution (Windows) - keep this as backup for Windows | |
- name: Package distribution (Windows) | |
if: runner.os == 'Windows' | |
run: | | |
mkdir -p dist\flex | |
copy src\dist\flex.exe dist\flex\ | |
xcopy src\flex_tester dist\flex\examples\ /E /I | |
copy README.md dist\flex\ | |
powershell Compress-Archive -Path dist\flex -DestinationPath flex-%VERSION%-${{ matrix.asset_name }}.zip | |
shell: cmd | |
- name: Debug - List files before upload | |
run: | | |
if [ "$RUNNER_OS" == "Windows" ]; then | |
echo "=== Current directory files ===" | |
dir | |
echo "=== src/dist directory files ===" | |
dir src\dist || echo "Directory not found" | |
echo "=== Current directory - find all flex files ===" | |
dir /s /b flex* 2>nul || echo "No files found" | |
else | |
echo "=== Current directory files ===" | |
ls -la | |
echo "=== src/dist directory files ===" | |
ls -la src/dist || true | |
echo "=== Current directory - find all flex files ===" | |
find . -name "flex*" -type f || true | |
fi | |
shell: bash | |
- name: Upload build artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: flex-${{ matrix.asset_name }} | |
path: | | |
flex-*-${{ matrix.asset_name }}.tar.gz | |
flex-*-${{ matrix.asset_name }}.zip | |
flex-*-win.exe | |
flex-*-mac.dmg | |
flex-*-linux.AppImage | |
flex-*-linux.deb | |
latest-*.yml | |
src/dist/flex* | |
if-no-files-found: warn | |
release: | |
name: Create Release | |
needs: build | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' | |
steps: | |
- uses: actions/checkout@v3 | |
- name: Set up version information | |
id: version | |
run: | | |
if [[ $GITHUB_REF == refs/tags/v* ]]; then | |
VERSION=${GITHUB_REF#refs/tags/v} | |
IS_PRERELEASE=false | |
RELEASE_NAME="Flex ${GITHUB_REF#refs/tags/v}" | |
TAG_NAME=${GITHUB_REF#refs/tags/} | |
else | |
VERSION="dev-$(date +'%Y%m%d')-${GITHUB_SHA::7}" | |
IS_PRERELEASE=true | |
RELEASE_NAME="Flex Latest Build" | |
TAG_NAME="latest" | |
fi | |
echo "VERSION=$VERSION" >> $GITHUB_ENV | |
echo "IS_PRERELEASE=$IS_PRERELEASE" >> $GITHUB_ENV | |
echo "RELEASE_NAME=$RELEASE_NAME" >> $GITHUB_ENV | |
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV | |
echo "version=$VERSION" >> $GITHUB_OUTPUT | |
shell: bash | |
- name: Download all artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
path: artifacts | |
- name: Prepare release assets | |
run: | | |
mkdir -p release_assets temp_source | |
# Create a clean source copy using a more selective approach | |
echo "Creating source code archives..." | |
git ls-files | while read file; do | |
# Create the target directory structure | |
mkdir -p "temp_source/$(dirname "$file")" | |
# Copy each file | |
cp "$file" "temp_source/$file" | |
done | |
# Create archives from the clean copy | |
(cd temp_source && zip -r ../release_assets/flex-${VERSION}-source.zip .) | |
(cd temp_source && tar --exclude='.DS_Store' -czf ../release_assets/flex-${VERSION}-source.tar.gz .) | |
# Clean up temporary directory | |
rm -rf temp_source | |
# Find and copy all relevant files to release_assets directory | |
echo "=== Copying artifacts to release directory ===" | |
for artifact_dir in artifacts/*/; do | |
echo "Processing ${artifact_dir}..." | |
find "${artifact_dir}" -type f \( \ | |
-name "*.tar.gz" -o \ | |
-name "*.zip" -o \ | |
-name "*.exe" -o \ | |
-name "*.dmg" -o \ | |
-name "*.AppImage" -o \ | |
-name "*.deb" -o \ | |
-name "*.yml" -o \ | |
-name "flex" -o \ | |
-name "flex.exe" \ | |
\) -exec cp {} release_assets/ \; || true | |
done | |
# Rename the release assets if needed to match proper versioning pattern | |
if [ ! -f "release_assets/latest-win.yml" ]; then | |
# Copy one of the platform YMLs as the main latest.yml | |
if [ -f "release_assets/latest-mac.yml" ]; then | |
cp release_assets/latest-mac.yml release_assets/latest.yml | |
elif [ -f "release_assets/latest-linux.yml" ]; then | |
cp release_assets/latest-linux.yml release_assets/latest.yml | |
fi | |
else | |
cp release_assets/latest-win.yml release_assets/latest.yml | |
fi | |
echo "=== Files in release_assets ===" | |
ls -la release_assets/ | |
shell: bash | |
- name: List downloaded files | |
run: | | |
echo "=== Root directory ===" | |
find . -type f -maxdepth 1 | sort | |
echo "=== All flex files ===" | |
find . -name "flex*" -type f | sort | |
echo "=== All artifacts directories ===" | |
find artifacts -type d | sort | |
echo "=== All artifact files ===" | |
find artifacts -type f | sort | |
echo "=== All release_assets files ===" | |
find release_assets -type f | sort | |
shell: bash | |
- name: Create Release | |
id: create_release | |
uses: softprops/action-gh-release@v1 | |
with: | |
name: ${{ env.RELEASE_NAME }} | |
tag_name: ${{ env.TAG_NAME }} | |
draft: false | |
prerelease: ${{ env.IS_PRERELEASE }} | |
files: release_assets/* | |
body: | | |
# ${{ env.RELEASE_NAME }} | |
Cross-platform executable releases of the Flex programming language. | |
## Installation | |
### Windows | |
- Option 1: Download and run `flex-${{ env.VERSION }}-win.exe` for a full installer with start menu shortcuts | |
- Option 2: Download and extract `flex-${{ env.VERSION }}-windows.zip`, then run `flex.exe` | |
### macOS | |
- Option 1: Download `flex-${{ env.VERSION }}-mac.dmg`, open and drag to Applications folder | |
- Option 2: Download and extract `flex-${{ env.VERSION }}-macos.tar.gz`, then run `flex` | |
### Linux | |
- Option 1: Download `flex-${{ env.VERSION }}-linux.AppImage`, make executable with `chmod +x flex-${{ env.VERSION }}-linux.AppImage` and run | |
- Option 2: Download `flex-${{ env.VERSION }}-linux.deb` and install with `sudo dpkg -i flex-${{ env.VERSION }}-linux.deb` | |
- Option 3: Download and extract `flex-${{ env.VERSION }}-linux.tar.gz`, then run `flex` | |
## Examples | |
Example code is included in the examples directory. | |
## Source Code | |
Source code is available as ZIP or TAR.GZ archive. | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |