feat: add reusable Flutter build actions for android, ios, macos, windows, and linux
Update README Actions Table / update-readme (push) Successful in 7s
Update README Actions Table / update-readme (push) Successful in 7s
This commit is contained in:
@@ -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'
|
||||
```
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user