Fix CI release race: use gh CLI + || true for idempotent creates #20
Workflow file for this run
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: AppImage | |
| on: | |
| push: | |
| tags: ['*'] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| appimage: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| environment: [humble, jazzy, kilted] | |
| runs-on: ubuntu-latest | |
| name: appimage-${{ matrix.environment }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: prefix-dev/setup-pixi@v0.9.4 | |
| with: | |
| environments: ${{ matrix.environment }} | |
| locked: true | |
| cache: true | |
| - name: Build | |
| run: pixi run -e ${{ matrix.environment }} build | |
| - name: Create AppImage | |
| run: | | |
| # Download linuxdeploy | |
| wget -q https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage | |
| chmod +x linuxdeploy-x86_64.AppImage | |
| CONDA_PREFIX="$(pixi run -e ${{ matrix.environment }} printenv CONDA_PREFIX)" | |
| # Create AppDir structure | |
| mkdir -p AppDir/usr/{bin,lib,share} | |
| # Copy binary (colcon isolated-install layout) | |
| cp install/pj_bridge/lib/pj_bridge/pj_bridge_ros2 AppDir/usr/bin/ | |
| # Bundle shared libraries from the conda environment | |
| # (exclude glibc/ld-linux which must come from the host) | |
| ldd AppDir/usr/bin/pj_bridge_ros2 | \ | |
| grep "$CONDA_PREFIX" | \ | |
| awk '{print $3}' | \ | |
| xargs -I{} cp --no-dereference {} AppDir/usr/lib/ 2>/dev/null || true | |
| # Also copy transitive deps from conda lib/ | |
| for lib in AppDir/usr/lib/*.so*; do | |
| ldd "$lib" 2>/dev/null | \ | |
| grep "$CONDA_PREFIX" | \ | |
| awk '{print $3}' | \ | |
| xargs -I{} cp --no-dereference {} AppDir/usr/lib/ 2>/dev/null || true | |
| done | |
| # Copy ament index (needed for schema discovery at runtime) | |
| cp -r "$CONDA_PREFIX"/share/ament_index AppDir/usr/share/ 2>/dev/null || true | |
| # Copy message definitions (.msg/.srv/.idl files) | |
| for pkg_dir in "$CONDA_PREFIX"/share/*/msg "$CONDA_PREFIX"/share/*/srv; do | |
| [ -d "$pkg_dir" ] || continue | |
| pkg_name="$(basename "$(dirname "$pkg_dir")")" | |
| mkdir -p "AppDir/usr/share/$pkg_name" | |
| cp -r "$pkg_dir" "AppDir/usr/share/$pkg_name/" | |
| done | |
| # Create .desktop file | |
| cat > AppDir/pj_bridge.desktop <<'DESKTOP' | |
| [Desktop Entry] | |
| Name=pj_bridge | |
| Exec=pj_bridge_ros2 | |
| Icon=pj_bridge | |
| Type=Application | |
| Categories=Science; | |
| DESKTOP | |
| # Create minimal icon | |
| convert -size 256x256 xc:transparent AppDir/pj_bridge.png 2>/dev/null || \ | |
| touch AppDir/pj_bridge.png | |
| # Create AppRun wrapper that sets environment | |
| cat > AppDir/AppRun <<'APPRUN' | |
| #!/bin/bash | |
| SELF="$(readlink -f "$0")" | |
| HERE="${SELF%/*}" | |
| export LD_LIBRARY_PATH="${HERE}/usr/lib:${LD_LIBRARY_PATH}" | |
| export AMENT_PREFIX_PATH="${AMENT_PREFIX_PATH:+$AMENT_PREFIX_PATH:}${HERE}/usr" | |
| exec "${HERE}/usr/bin/pj_bridge_ros2" "$@" | |
| APPRUN | |
| chmod +x AppDir/AppRun | |
| # Generate AppImage (LD_LIBRARY_PATH needed for linuxdeploy to find conda libs) | |
| export LD_LIBRARY_PATH="$CONDA_PREFIX/lib:${LD_LIBRARY_PATH:-}" | |
| ARCH=x86_64 ./linuxdeploy-x86_64.AppImage \ | |
| --appdir AppDir \ | |
| --output appimage | |
| - name: Rename AppImage | |
| run: | | |
| rm -f linuxdeploy-x86_64.AppImage | |
| mv *.AppImage pj_bridge_ros2-${{ matrix.environment }}-x86_64.AppImage | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: appimage-${{ matrix.environment }} | |
| path: "*.AppImage" | |
| release: | |
| needs: appimage | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: artifacts | |
| pattern: appimage-* | |
| merge-multiple: true | |
| - name: Upload to GitHub Release | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| GH_REPO: ${{ github.repository }} | |
| run: | | |
| tag="${{ github.ref_name }}" | |
| # Create release if it doesn't exist yet | |
| gh release view "$tag" >/dev/null 2>&1 || \ | |
| gh release create "$tag" --title "$tag" --generate-notes || true | |
| # Upload assets (--clobber overwrites if re-run) | |
| gh release upload "$tag" artifacts/*.AppImage --clobber |