feat: add reusable Flutter build actions for android, ios, macos, windows, and linux
Update README Actions Table / update-readme (push) Successful in 7s

This commit is contained in:
2026-10-18 13:55:08 -07:00
parent 56dd7d58b3
commit 7a12bb1cc6
11 changed files with 1669 additions and 0 deletions
+43
View File
@@ -0,0 +1,43 @@
# Flutter Build Linux
Composite action to install Linux GTK3 build dependencies, compile Linux Flutter desktop applications, package `.deb` and `.tar.gz` installers, and generate release metadata.
## Inputs
| Name | Description | Required | Default |
| :--- | :--- | :--- | :--- |
| `working_directory` | Path to the Flutter app package directory. | No | `.` |
| `arch` | Target Linux architecture (`amd64` / `x64` or `arm64`). | No | `amd64` |
| `build_args` | Extra arguments passed to `flutter build linux`. | No | `''` |
| `install_deps` | Install Linux GTK3 & CMake build dependencies via `apt-get`. | No | `true` |
| `auto_create_linux_runner` | Automatically run `flutter create --platforms=linux .` if `linux/` directory is missing. | No | `true` |
| `output_dir` | Output directory for packaged `.deb` and `.tar.gz` archives. | No | `dist` |
| `package_script` | Optional custom packaging script in repository (e.g., `scripts/package_linux.sh`). | No | `scripts/package_linux.sh` |
| `app_name` | Application display name for `.desktop` entry. | No | `Slides for Worship` |
| `package_name` | Debian package slug (e.g., `slides-for-worship`). | No | `slides-for-worship` |
| `binary_name` | Compiled Linux executable name inside bundle (auto-detected if empty). | No | `''` |
| `icon_path` | Path to app icon PNG relative to `working_directory`. | No | `assets/icon.png` |
| `maintainer` | Debian package maintainer string. | No | `Rody Davis <rody.davis.jr@gmail.com>` |
| `description` | Debian package description. | No | `Professional worship slide production and presentation studio.` |
| `generate_metadata_json` | Whether to generate `linux_<arch>_metadata.json`. | No | `false` |
## Outputs
| Name | Description |
| :--- | :--- |
| `version` | Resolved package version from `pubspec.yaml`. |
| `deb_path` | Path to generated `.deb` package. |
| `tar_path` | Path to generated `.tar.gz` archive. |
| `metadata_path` | Path to generated `linux_<arch>_metadata.json`. |
## Example Usage
```yaml
- name: Build & Package Linux Release
uses: rodydavis/shared-actions/flutter-build-linux@main
with:
working_directory: packages/sfw_desktop
arch: ${{ matrix.arch }}
build_args: --dart-define=API_BASE_URL=https://slidesforworship.app
generate_metadata_json: 'true'
```
+230
View File
@@ -0,0 +1,230 @@
name: 'Flutter Build Linux'
description: 'Installs GTK3/Linux build dependencies, builds Linux Flutter desktop apps, packages .tar.gz and .deb installers, and generates release metadata.'
inputs:
working_directory:
description: 'Path to the Flutter app package directory (e.g., packages/sfw_desktop)'
required: false
default: '.'
arch:
description: 'Target Linux architecture (amd64 / x64 or arm64)'
required: false
default: 'amd64'
build_args:
description: 'Extra arguments passed to flutter build linux (e.g., --dart-define=...)'
required: false
default: ''
install_deps:
description: 'Install Linux GTK3 & CMake build dependencies via apt-get'
required: false
default: 'true'
auto_create_linux_runner:
description: 'Automatically run flutter create --platforms=linux . if linux/ directory is missing'
required: false
default: 'true'
output_dir:
description: 'Output directory for packaged .deb and .tar.gz archives'
required: false
default: 'dist'
package_script:
description: 'Optional custom packaging script in repository (e.g., scripts/package_linux.sh)'
required: false
default: 'scripts/package_linux.sh'
app_name:
description: 'Application display name for .desktop entry (used if package_script is not present)'
required: false
default: 'Slides for Worship'
package_name:
description: 'Debian package slug (e.g., slides-for-worship)'
required: false
default: 'slides-for-worship'
binary_name:
description: 'Compiled Linux executable name inside bundle (auto-detected if empty)'
required: false
default: ''
icon_path:
description: 'Path to app icon PNG relative to working_directory'
required: false
default: 'assets/icon.png'
maintainer:
description: 'Debian package maintainer string'
required: false
default: 'Rody Davis <rody.davis.jr@gmail.com>'
description:
description: 'Debian package description'
required: false
default: 'Professional worship slide production and presentation studio.'
generate_metadata_json:
description: 'Whether to generate linux_<arch>_metadata.json'
required: false
default: 'false'
outputs:
version:
description: 'Resolved package version from pubspec.yaml'
value: ${{ steps.build.outputs.version }}
deb_path:
description: 'Path to generated .deb package'
value: ${{ steps.package.outputs.deb_path }}
tar_path:
description: 'Path to generated .tar.gz archive'
value: ${{ steps.package.outputs.tar_path }}
metadata_path:
description: 'Path to generated linux_<arch>_metadata.json'
value: ${{ steps.package.outputs.metadata_path }}
runs:
using: 'composite'
steps:
- name: Install Linux Build Dependencies
if: inputs.install_deps == 'true' && runner.os == 'Linux'
shell: bash
run: |
if command -v apt-get >/dev/null 2>&1; then
SUDO=""
if [ "$(id -u)" -ne 0 ] && command -v sudo >/dev/null 2>&1; then
SUDO="sudo"
fi
$SUDO apt-get update
$SUDO apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev dpkg-dev
fi
- name: Build Linux Release
id: build
shell: bash
env:
WORK_DIR: ${{ inputs.working_directory }}
ARCH: ${{ inputs.arch }}
BUILD_ARGS: ${{ inputs.build_args }}
AUTO_CREATE: ${{ inputs.auto_create_linux_runner }}
run: |
ROOT_DIR="$(pwd)"
VERSION=$(grep '^version: ' "$WORK_DIR/pubspec.yaml" | head -n 1 | cut -d ' ' -f 2 | tr -d '\r')
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
cd "$WORK_DIR"
flutter config --enable-linux-desktop
if [ ! -d "linux" ] && [ "$AUTO_CREATE" = "true" ]; then
echo "Notice: '$WORK_DIR/linux' directory not found. Scaffolding Linux runner via 'flutter create --platforms=linux .'..."
flutter create --platforms=linux .
fi
if [ "$ARCH" = "arm64" ] || [ "$ARCH" = "aarch64" ]; then
# shellcheck disable=SC2086
flutter build linux --release --target-platform=linux-arm64 $BUILD_ARGS
else
# shellcheck disable=SC2086
flutter build linux --release $BUILD_ARGS
fi
cd "$ROOT_DIR"
- name: Package Linux Installers (.deb & .tar.gz) & Metadata
id: package
shell: bash
env:
WORK_DIR: ${{ inputs.working_directory }}
ARCH_INPUT: ${{ inputs.arch }}
OUT_DIR: ${{ inputs.output_dir }}
PKG_SCRIPT: ${{ inputs.package_script }}
APP_NAME: ${{ inputs.app_name }}
PKG_NAME: ${{ inputs.package_name }}
BIN_NAME: ${{ inputs.binary_name }}
ICON_REL: ${{ inputs.icon_path }}
MAINTAINER: ${{ inputs.maintainer }}
DESC: ${{ inputs.description }}
VERSION: ${{ steps.build.outputs.version }}
GEN_META: ${{ inputs.generate_metadata_json }}
run: |
ROOT_DIR="$(pwd)"
if [ "$ARCH_INPUT" = "arm64" ] || [ "$ARCH_INPUT" = "aarch64" ]; then
DEB_ARCH="arm64"
BUNDLE_DIR="$WORK_DIR/build/linux/arm64/release/bundle"
else
DEB_ARCH="amd64"
BUNDLE_DIR="$WORK_DIR/build/linux/x64/release/bundle"
fi
mkdir -p "$OUT_DIR"
if [ -n "$PKG_SCRIPT" ] && [ -f "$PKG_SCRIPT" ]; then
echo "Running repository packaging script: $PKG_SCRIPT..."
bash "$PKG_SCRIPT" "$VERSION" "$DEB_ARCH" "$BUNDLE_DIR"
else
echo "Packaging .tar.gz and .deb directly..."
TAR_NAME="${PKG_NAME}-linux-${DEB_ARCH}.tar.gz"
tar -czf "$OUT_DIR/$TAR_NAME" -C "$BUNDLE_DIR" .
DEB_DIR="$WORK_DIR/build/deb_pkg_${DEB_ARCH}"
rm -rf "$DEB_DIR"
mkdir -p "$DEB_DIR/DEBIAN"
mkdir -p "$DEB_DIR/usr/bin"
mkdir -p "$DEB_DIR/usr/share/${PKG_NAME}"
mkdir -p "$DEB_DIR/usr/share/applications"
mkdir -p "$DEB_DIR/usr/share/icons/hicolor/512x512/apps"
cp -r "$BUNDLE_DIR"/* "$DEB_DIR/usr/share/${PKG_NAME}/"
if [ -z "$BIN_NAME" ]; then
BIN_NAME=$(grep '^name: ' "$WORK_DIR/pubspec.yaml" | head -n 1 | cut -d ' ' -f 2 | tr -d '\r')
fi
ln -sf "/usr/share/${PKG_NAME}/${BIN_NAME}" "$DEB_DIR/usr/bin/${PKG_NAME}"
if [ -f "$WORK_DIR/$ICON_REL" ]; then
cp "$WORK_DIR/$ICON_REL" "$DEB_DIR/usr/share/icons/hicolor/512x512/apps/${PKG_NAME}.png"
fi
cat <<EOF > "$DEB_DIR/usr/share/applications/${PKG_NAME}.desktop"
[Desktop Entry]
Name=$APP_NAME
Comment=$DESC
Exec=/usr/bin/$PKG_NAME
Icon=$PKG_NAME
Terminal=false
Type=Application
Categories=AudioVideo;Presentation;Utility;
EOF
CLEAN_VERSION=$(echo "$VERSION" | cut -d'+' -f1)
cat <<EOF > "$DEB_DIR/DEBIAN/control"
Package: $PKG_NAME
Version: $CLEAN_VERSION
Section: utils
Priority: optional
Architecture: $DEB_ARCH
Maintainer: $MAINTAINER
Description: $APP_NAME
$DESC
EOF
dpkg-deb --build "$DEB_DIR" "$OUT_DIR/${PKG_NAME}-linux-${DEB_ARCH}.deb"
fi
DEB_FILE=$(find "$OUT_DIR" -name "*-linux-${DEB_ARCH}.deb" 2>/dev/null | head -n 1 || true)
TAR_FILE=$(find "$OUT_DIR" -name "*-linux-${DEB_ARCH}.tar.gz" 2>/dev/null | head -n 1 || true)
echo "deb_path=$DEB_FILE" >> "$GITHUB_OUTPUT"
echo "tar_path=$TAR_FILE" >> "$GITHUB_OUTPUT"
if [ "$GEN_META" = "true" ]; then
PRIMARY_FILE="${DEB_FILE:-$TAR_FILE}"
SIZE="0"
FILENAME="${PKG_NAME}-linux-${DEB_ARCH}.deb"
if [ -n "$PRIMARY_FILE" ] && [ -f "$PRIMARY_FILE" ]; then
SIZE=$(stat -c%s "$PRIMARY_FILE" 2>/dev/null || stat -f%z "$PRIMARY_FILE" 2>/dev/null || echo "0")
FILENAME=$(basename "$PRIMARY_FILE")
fi
META_FILE="linux_${DEB_ARCH}_metadata.json"
cat <<EOF > "$META_FILE"
{
"version": "$VERSION",
"platform": "linux",
"arch": "$DEB_ARCH",
"filename": "$FILENAME",
"size": $SIZE,
"signature": "",
"signatureType": "none"
}
EOF
cat "$META_FILE"
echo "metadata_path=$META_FILE" >> "$GITHUB_OUTPUT"
fi