diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4d9ef69..f197f20 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,24 +6,29 @@ on: - 'v*' jobs: + check-tag: + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - id: set-matrix + run: | + TAG=${GITHUB_REF_NAME} + if [[ "$TAG" == *"-linux" ]]; then + echo 'matrix={"include":[{"os":"ubuntu-latest","artifact_name":"disco-reaper-linux","asset_name":"disco-reaper-linux.zip","executable_path":"dist/DiscoReaper"}]}' >> $GITHUB_OUTPUT + elif [[ "$TAG" == *"-windows" ]]; then + echo 'matrix={"include":[{"os":"windows-latest","artifact_name":"disco-reaper-windows","asset_name":"disco-reaper-windows.zip","executable_path":"dist/DiscoReaper.exe"}]}' >> $GITHUB_OUTPUT + elif [[ "$TAG" == *"-mac" ]]; then + echo 'matrix={"include":[{"os":"macos-latest","artifact_name":"disco-reaper-macos","asset_name":"disco-reaper-macos.zip","executable_path":"dist/DiscoReaper"}]}' >> $GITHUB_OUTPUT + else + echo 'matrix={"include":[{"os":"ubuntu-latest","artifact_name":"disco-reaper-linux","asset_name":"disco-reaper-linux.zip","executable_path":"dist/DiscoReaper"},{"os":"windows-latest","artifact_name":"disco-reaper-windows","asset_name":"disco-reaper-windows.zip","executable_path":"dist/DiscoReaper.exe"},{"os":"macos-latest","artifact_name":"disco-reaper-macos","asset_name":"disco-reaper-macos.zip","executable_path":"dist/DiscoReaper"}]}' >> $GITHUB_OUTPUT + fi + build: + needs: check-tag runs-on: ${{ matrix.os }} strategy: - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - include: - - os: ubuntu-latest - artifact_name: disco-reaper-linux - asset_name: disco-reaper-linux.zip - executable_path: dist/DiscoReaper - - os: windows-latest - artifact_name: disco-reaper-windows - asset_name: disco-reaper-windows.zip - executable_path: dist/DiscoReaper.exe - - os: macos-latest - artifact_name: disco-reaper-macos - asset_name: disco-reaper-macos.zip - executable_path: dist/DiscoReaper + matrix: ${{ fromJson(needs.check-tag.outputs.matrix) }} steps: - name: Checkout code @@ -40,7 +45,6 @@ jobs: pip install -r requirements.txt pip install pyinstaller Pillow - - name: Bake Version shell: bash run: | @@ -59,15 +63,32 @@ jobs: - name: Prepare Release Asset (Linux/MacOS) if: matrix.os == 'ubuntu-latest' || matrix.os == 'macos-latest' run: | - cp ${{ matrix.executable_path }} DiscoReaper - chmod +x DiscoReaper - zip ${{ matrix.asset_name }} DiscoReaper + mkdir REAPER + cp ${{ matrix.executable_path }} REAPER/DiscoReaper + chmod +x REAPER/DiscoReaper + + # Create launcher for Linux/Mac + cat << 'EOF' > REAPER/Launch-Reaper.sh + #!/bin/bash + BASEDIR=$(dirname "$0") + cd "$BASEDIR" + if [ -f "./DiscoReaper" ]; then + ./DiscoReaper + else + echo "Error: DiscoReaper binary not found." + read -p "Press enter to exit..." + fi + EOF + chmod +x REAPER/Launch-Reaper.sh + + zip -r ${{ matrix.asset_name }} REAPER - name: Prepare Release Asset (Windows) if: matrix.os == 'windows-latest' run: | - copy ${{ matrix.executable_path }} DiscoReaper.exe - powershell Compress-Archive -Path "DiscoReaper.exe" -DestinationPath "${{ matrix.asset_name }}" + mkdir REAPER + copy ${{ matrix.executable_path }} REAPER\DiscoReaper.exe + powershell Compress-Archive -Path "REAPER" -DestinationPath "${{ matrix.asset_name }}" - name: Upload Artifact uses: actions/upload-artifact@v4 @@ -89,9 +110,6 @@ jobs: - name: Create Release uses: softprops/action-gh-release@v2 with: - files: | - artifacts/disco-reaper-linux/disco-reaper-linux.zip - artifacts/disco-reaper-windows/disco-reaper-windows.zip - artifacts/disco-reaper-macos/disco-reaper-macos.zip + files: artifacts/**/*.zip env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/disco-reaper.py b/disco-reaper.py index bc27def..f773d6c 100644 --- a/disco-reaper.py +++ b/disco-reaper.py @@ -59,6 +59,35 @@ def relaunch_in_terminal(): except Exception: continue +def setup_ssl(): + """Configures SSL certificate paths for frozen environments.""" + import os + import sys + + # Only strictly necessary for frozen builds on Linux/macOS + if not getattr(sys, 'frozen', False): + return + + try: + import certifi + ca_file = certifi.where() + os.environ["SSL_CERT_FILE"] = ca_file + os.environ["REQUESTS_CA_BUNDLE"] = ca_file + except ImportError: + # Fallback to common Linux CA bundle paths + ca_paths = [ + "/etc/ssl/certs/ca-certificates.crt", + "/etc/pki/tls/certs/ca-bundle.crt", + "/etc/ssl/ca-bundle.pem", + "/etc/pki/tls/cacert.pem", + "/etc/ssl/cert.pem", + ] + for path in ca_paths: + if os.path.exists(path): + os.environ["SSL_CERT_FILE"] = path + os.environ["REQUESTS_CA_BUNDLE"] = path + break + def main(): import os # Ensure screenshots directory is configured (but not created yet) @@ -66,6 +95,7 @@ def main(): os.environ["TEXTUAL_SCREENSHOT_LOCATION"] = shot_path relaunch_in_terminal() + setup_ssl() setup_logging() run_disco_reaper_tui() diff --git a/src/ui/shuttle_ops.py b/src/ui/shuttle_ops.py index 1cd690e..ecd947e 100644 --- a/src/ui/shuttle_ops.py +++ b/src/ui/shuttle_ops.py @@ -212,6 +212,8 @@ class OperationPane(Container): # ── labels ──────────────────────────────────────────────────────────── def _update_info_labels(self): + if not self.is_mounted: + return v = self.validation_results # Discord @@ -339,6 +341,8 @@ class OperationPane(Container): @work(exclusive=True) async def run_validate(self) -> None: + if not self.is_mounted: + return try: plat = "Fluxer" if self.target_platform == "fluxer" else "Stoat" self.query_one("#op_lbl_t_header", Label).update(plat)