Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 87 additions & 197 deletions .github/workflows/build-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,50 +10,32 @@ on:
type: string

jobs:
build-server-windows:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: Install dependencies
run: |
cd backend
python -m pip install --upgrade pip
pip install -r requirements.txt
pip uninstall -y onnxruntime
pip install onnxruntime-directml

- name: Build executable with PyInstaller
run: |
cd backend
pyinstaller main.py --name PictoPy_Server --onedir --distpath dist

- name: Copy app folder
run: |
cd backend
mkdir dist/PictoPy_Server/images
robocopy app dist\PictoPy_Server\app /e
if ($LASTEXITCODE -le 1) { exit 0 }

- name: Create ZIP package
run: |
cd backend/dist/PictoPy_Server
tar -a -c -f PictoPy-Windows.zip .

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PictoPy-Windows
path: backend/dist/PictoPy_Server/PictoPy-Windows.zip

build-server-ubuntu:
runs-on: ubuntu-22.04
build-server:
strategy:
fail-fast: false
matrix:
include:
- platform: windows-latest
artifact-name: PictoPy-Windows
onnx-package: onnxruntime-directml
mkdir-cmd: mkdir dist/PictoPy_Server/images
copy-cmd: |
robocopy app dist\PictoPy_Server\app /e
if ($LASTEXITCODE -le 1) { exit 0 }
zip-cmd: tar -a -c -f PictoPy-Windows.zip .
- platform: ubuntu-22.04
artifact-name: PictoPy-Ubuntu
onnx-package: onnxruntime-gpu
mkdir-cmd: mkdir -p dist/PictoPy_Server/images && mkdir -p dist/PictoPy_Server/app
copy-cmd: cp -r app/* dist/PictoPy_Server/app/
zip-cmd: zip -r PictoPy-Ubuntu.zip .
- platform: macos-latest
artifact-name: PictoPy-MacOS
onnx-package: ""
mkdir-cmd: mkdir -p dist/PictoPy_Server/images && mkdir -p dist/PictoPy_Server/app
copy-cmd: cp -r app/* dist/PictoPy_Server/app/
zip-cmd: zip -r PictoPy-MacOS.zip .
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -62,120 +44,65 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: 3.12
cache: 'pip'
cache-dependency-path: backend/requirements.txt

- name: Install dependencies
working-directory: backend
shell: bash
run: |
cd backend
python -m pip install --upgrade pip
pip install -r requirements.txt
pip uninstall -y onnxruntime
pip install onnxruntime-gpu
if [ -n "${{ matrix.onnx-package }}" ]; then
pip uninstall -y onnxruntime
pip install ${{ matrix.onnx-package }}
fi

- name: Build executable with PyInstaller
working-directory: backend
run: |
cd backend
pyinstaller main.py --name PictoPy_Server --onedir --distpath dist

- name: Copy app folder
working-directory: backend
shell: ${{ matrix.platform == 'windows-latest' && 'pwsh' || 'bash' }}
run: |
cd backend
mkdir -p dist/PictoPy_Server/images
mkdir -p dist/PictoPy_Server/app
cp -r app/* dist/PictoPy_Server/app/

- name: Create ZIP package
run: |
cd backend/dist/PictoPy_Server
zip -r PictoPy-Ubuntu.zip .

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PictoPy-Ubuntu
path: backend/dist/PictoPy_Server/PictoPy-Ubuntu.zip

build-server-macos:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: Install dependencies
run: |
cd backend
python -m pip install --upgrade pip
pip install -r requirements.txt

- name: Build executable with PyInstaller
run: |
cd backend
pyinstaller main.py --name PictoPy_Server --onedir --distpath dist
${{ matrix.mkdir-cmd }}
${{ matrix.copy-cmd }}

- name: Copy app folder
run: |
cd backend
mkdir -p dist/PictoPy_Server/images
mkdir -p dist/PictoPy_Server/app
cp -r app/* dist/PictoPy_Server/app/

- name: Create ZIP package
run: |
cd backend/dist/PictoPy_Server
zip -r PictoPy-MacOS.zip .

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PictoPy-MacOS
path: backend/dist/PictoPy_Server/PictoPy-MacOS.zip

build-sync-microservice-windows:
runs-on: windows-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: Install dependencies
run: |
cd sync-microservice
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller

- name: Build executable with PyInstaller
run: |
cd sync-microservice
pyinstaller main.py --name PictoPy_Sync --onedir --distpath dist

- name: Copy app folder
run: |
cd sync-microservice
robocopy app dist\PictoPy_Sync\app /e
if ($LASTEXITCODE -le 1) { exit 0 }

- name: Create ZIP package
working-directory: backend/dist/PictoPy_Server
shell: bash
run: |
cd sync-microservice/dist/PictoPy_Sync
tar -a -c -f PictoPy-Sync-Windows.zip .
${{ matrix.zip-cmd }}
Comment on lines 74 to +78
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the workflow file to see the exact code
cat -n .github/workflows/build-and-release.yml | sed -n '13,150p'

Repository: AOSSIE-Org/PictoPy

Length of output: 5698


🏁 Script executed:

# Also check the specific lines 74-78 mentioned
cat -n .github/workflows/build-and-release.yml | sed -n '70,85p'

Repository: AOSSIE-Org/PictoPy

Length of output: 604


🏁 Script executed:

# Check the sync microservice zip step at lines 136-140
cat -n .github/workflows/build-and-release.yml | sed -n '132,145p'

Repository: AOSSIE-Org/PictoPy

Length of output: 502


🏁 Script executed:

# Verify the matrix definition including zip-cmd
cat -n .github/workflows/build-and-release.yml | sed -n '13,38p'

Repository: AOSSIE-Org/PictoPy

Length of output: 1359


🏁 Script executed:

# Check GNU tar documentation for -a flag behavior
# Let's search for information about tar -a with zip files in the codebase context
rg -i "tar.*-a.*zip|zip.*tar.*-a" || echo "No mixed tar/zip commands found in other files"

Repository: AOSSIE-Org/PictoPy

Length of output: 108


🌐 Web query:

GNU tar -a flag .zip format support Windows

💡 Result:

  • GNU tar: -a/--auto-compress only auto-selects a compression filter for a tar archive based on the filename suffix (e.g., .tar.gz, .tar.xz). The GNU tar manual lists the supported compressors (gzip, bzip2, xz, zstd, etc.) and does not include ZIP, because ZIP is a different archive format, not a tar compression filter. So GNU tar cannot create a real .zip with -a. [1][5][6]

  • Windows “tar.exe” (often not GNU tar): The tar that ships with modern Windows is typically bsdtar/libarchive, where -a does pick the archive format from the suffix, and archive.zip results in ZIP format (i.e., it can create ZIP). [2][3]

So: if you’re using GNU tar, tar -a -cf something.zip ... won’t produce a proper ZIP; if you’re using Windows’ built-in tar (bsdtar), it generally will.

Sources:
[1] GNU tar manual: supported compression programs (no zip)
[2] bsdtar man page (-a example shows archive.zip creates zip format)
[3] libarchive/bsdtar on Windows (issue describing Windows-included bsdtar)
[5] Explanation why GNU tar doesn’t handle zip like gzip/bzip2 filters
[6] GNU tar manual entry for --auto-compress (suffix-based compressed format recognition)


🌐 Web query:

GitHub Actions Windows bash shell Git Bash GNU tar vs Windows tar

💡 Result:

On GitHub Actions Windows runners, you can easily end up with different tar implementations depending on which shell/command is actually being used.

Which bash is used when you set shell: bash?

On Windows, shell: bash runs Git for Windows’ Git Bash explicitly:
C:\Program Files\Git\bin\bash.exe --noprofile --norc -e -o pipefail {0}. [1]
And the hosted image documents that gitbash.exe points to that same bash.exe. [2]

“Windows tar” vs “GNU tar” (what you’re really getting)

  • Windows’ built-in tar is C:\Windows\System32\tar.exe, and it is bsdtar (libarchive-based). [3][4]
    Libarchive’s project explicitly provides the bsdtar tar implementation. [4]
  • GNU tar is what you typically get from Unix-like environments on Windows (MSYS2 / Git for Windows). MSYS2’s tar package is GNU tar (homepage is gnu.org; package name tar). [5]

Why this matters in Actions workflows

  • Some Actions/tools assume particular tar features/behavior. For example, actions/cache has Windows-specific behavior and notes that GNU tar (and zstd) are required/recommended on self-hosted Windows, especially for cross-OS caching. [6]
  • If your workflow modifies PATH, you may unintentionally switch which tar.exe is found first.

How to force one or the other

  • Force Windows bsdtar:
    • From Git Bash: /c/Windows/System32/tar.exe ...
    • Or use the full Windows path in any shell: C:\Windows\System32\tar.exe ... [3]
  • Force GNU tar:
    • Use MSYS2 explicitly (shell: msys2 {0}) after setting it up (MSYS2 is preinstalled but not on PATH by default). [2]
    • Or call the GNU tar binary from the MSYS2/Git toolchain by absolute path (varies by install; verify with which tar / tar --version).

Quick check: run tar --version

  • bsdtar prints something like bsdtar ... - libarchive ... [3][4]
  • GNU tar prints tar (GNU tar) ... [5]

Sources: [1] [2] [3] [4] [5] [6]


Critical bug: Windows tar -a -c -f *.zip will fail under shell: bash.

The Create ZIP package step (lines 74–78) forces shell: bash, but the Windows zip-cmd (tar -a -c -f PictoPy-Windows.zip .) relies on Windows' native tar.exe (bsdtar/libarchive), which supports creating .zip archives via the -a flag. Under shell: bash on GitHub Actions, Git Bash's GNU tar is used instead, and GNU tar does not support .zip as a target format—only compression filters (gzip, bzip2, xz, zstd, etc.) for tar archives. This will fail on the Windows matrix entry.

The same issue applies to the sync microservice zip step at lines 136–140.

Recommended fix: Use conditional shell (mirrors the copy step pattern)
      - name: Create ZIP package
        working-directory: backend/dist/PictoPy_Server
-       shell: bash
+       shell: ${{ matrix.platform == 'windows-latest' && 'pwsh' || 'bash' }}
        run: |
          ${{ matrix.zip-cmd }}

Apply the same change to the sync microservice step at lines 136–140.

🤖 Prompt for AI Agents
In @.github/workflows/build-and-release.yml around lines 74 - 78, The "Create
ZIP package" step forces shell: bash which causes Windows matrix entries to use
GNU tar (no -a zip support); update that step to use a conditional shell like
the project's copy step so Windows runs with PowerShell (pwsh) and non-Windows
runs with bash (i.e., choose pwsh when runner.os == 'Windows', bash otherwise)
so the Windows zip-cmd (tar -a -c -f ...) uses native tar.exe; apply the same
change to the sync microservice zip step as well.


- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PictoPy-Sync-Windows
path: sync-microservice/dist/PictoPy_Sync/PictoPy-Sync-Windows.zip
name: ${{ matrix.artifact-name }}
path: backend/dist/PictoPy_Server/${{ matrix.artifact-name }}.zip

build-sync-microservice-ubuntu:
runs-on: ubuntu-22.04
build-sync-microservice:
strategy:
fail-fast: false
matrix:
include:
- platform: windows-latest
artifact-name: PictoPy-Sync-Windows
copy-cmd: |
robocopy app dist\PictoPy_Sync\app /e
if ($LASTEXITCODE -le 1) { exit 0 }
zip-cmd: tar -a -c -f PictoPy-Sync-Windows.zip .
- platform: ubuntu-22.04
artifact-name: PictoPy-Sync-Ubuntu
copy-cmd: mkdir -p dist/PictoPy_Sync/app && cp -r app/* dist/PictoPy_Sync/app/
zip-cmd: zip -r PictoPy-Sync-Ubuntu.zip .
- platform: macos-latest
artifact-name: PictoPy-Sync-MacOS
copy-cmd: mkdir -p dist/PictoPy_Sync/app && cp -r app/* dist/PictoPy_Sync/app/
zip-cmd: zip -r PictoPy-Sync-MacOS.zip .
runs-on: ${{ matrix.platform }}
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -184,88 +111,44 @@ jobs:
uses: actions/setup-python@v4
with:
python-version: 3.12
cache: 'pip'
cache-dependency-path: sync-microservice/requirements.txt

- name: Install dependencies
working-directory: sync-microservice
run: |
cd sync-microservice
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller

- name: Build executable with PyInstaller
working-directory: sync-microservice
run: |
cd sync-microservice
pyinstaller main.py --name PictoPy_Sync --onedir --distpath dist

- name: Copy app folder
working-directory: sync-microservice
shell: ${{ matrix.platform == 'windows-latest' && 'pwsh' || 'bash' }}
run: |
cd sync-microservice
mkdir -p dist/PictoPy_Sync/app
cp -r app/* dist/PictoPy_Sync/app/
${{ matrix.copy-cmd }}

- name: Create ZIP package
run: |
cd sync-microservice/dist/PictoPy_Sync
zip -r PictoPy-Sync-Ubuntu.zip .

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PictoPy-Sync-Ubuntu
path: sync-microservice/dist/PictoPy_Sync/PictoPy-Sync-Ubuntu.zip

build-sync-microservice-macos:
runs-on: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: 3.12

- name: Install dependencies
run: |
cd sync-microservice
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install pyinstaller

- name: Build executable with PyInstaller
run: |
cd sync-microservice
pyinstaller main.py --name PictoPy_Sync --onedir --distpath dist

- name: Copy app folder
run: |
cd sync-microservice
mkdir -p dist/PictoPy_Sync/app
cp -r app/* dist/PictoPy_Sync/app/

- name: Create ZIP package
working-directory: sync-microservice/dist/PictoPy_Sync
shell: bash
run: |
cd sync-microservice/dist/PictoPy_Sync
zip -r PictoPy-Sync-MacOS.zip .
${{ matrix.zip-cmd }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: PictoPy-Sync-MacOS
path: sync-microservice/dist/PictoPy_Sync/PictoPy-Sync-MacOS.zip
name: ${{ matrix.artifact-name }}
path: sync-microservice/dist/PictoPy_Sync/${{ matrix.artifact-name }}.zip

publish-tauri:
permissions:
contents: write
needs:
[
build-server-windows,
build-server-ubuntu,
build-server-macos,
build-sync-microservice-windows,
build-sync-microservice-ubuntu,
build-sync-microservice-macos,
]
needs: [build-server, build-sync-microservice]
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -306,38 +189,45 @@ jobs:

- name: Extract server files
shell: bash
working-directory: backend/dist
run: |
cd backend/dist
unzip -o *.zip
rm *.zip
ls -l

- name: Extract sync microservice files
shell: bash
working-directory: sync-microservice/dist
run: |
cd sync-microservice/dist
unzip -o *.zip
rm *.zip
ls -l
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
cache: 'npm'
cache-dependency-path: frontend/package-lock.json

- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin' || '' }}

- name: Rust cache
uses: swatinem/rust-cache@v2
with:
workspaces: frontend/src-tauri

- name: Install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

- name: Install frontend dependencies
working-directory: frontend
run: |
cd frontend
npm install

- uses: tauri-apps/tauri-action@v0
Expand Down
Loading