diff --git a/.bazelignore b/.bazelignore index ccaf7168..db4d040d 100644 --- a/.bazelignore +++ b/.bazelignore @@ -1,3 +1,5 @@ # Convenience symlinks are blindly traversed by Bazel... # https://github.com/bazelbuild/bazel/issues/10653#issuecomment-694230015 bazel-rules_appimage + +examples diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4d680bbb..1d279e9e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -34,6 +34,10 @@ jobs: - run: bazel test --enable_bzlmod //... if: ${{ matrix.bazel-version != '5.x' }} + - run: ./integration_test.sh + working-directory: example + if: ${{ matrix.bazel-version != '5.x' }} + lint: runs-on: ubuntu-latest permissions: diff --git a/README.md b/README.md index a3dda85f..62e87b2a 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,9 @@ See the [latest release notes](https://github.com/lalten/rules_appimage/releases ### Usage -To package a binary target into an AppImage, you add a `appimage` rule and point it at the target. -So in your `BUILD` files you do: +There is example workspaces in [`examples/`](https://github.com/lalten/rules_appimage/blob/main/examples/README.md). + +To package a binary target into an AppImage, add an `appimage` rule in a `BUILD` file and point it at the target. ```py load("@rules_appimage//appimage:appimage.bzl", "appimage") @@ -42,7 +43,7 @@ appimage( There is also a `appimage_test` rule that takes the same arguments but runs the appimage as a Bazel test target. -## How to use the appimage +## How to run the appimage artifact ### Via Bazel diff --git a/examples/.bazelrc b/examples/.bazelrc new file mode 100644 index 00000000..3ce91d27 --- /dev/null +++ b/examples/.bazelrc @@ -0,0 +1 @@ +common --enable_bzlmod diff --git a/examples/BUILD b/examples/BUILD new file mode 100644 index 00000000..21249899 --- /dev/null +++ b/examples/BUILD @@ -0,0 +1,15 @@ +load("@py_deps//:requirements.bzl", "requirement") +load("@rules_appimage//appimage:appimage.bzl", "appimage") +load("@rules_python//python:defs.bzl", "py_binary") + +py_binary( + name = "hello", + srcs = ["hello.py"], + data = ["//resources"], + deps = [requirement("click")], +) + +appimage( + name = "hello.appimage", + binary = ":hello", +) diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel new file mode 100644 index 00000000..8f9c2674 --- /dev/null +++ b/examples/MODULE.bazel @@ -0,0 +1,16 @@ +"""Example workspace using rules_appimage.""" + +module(name = "rules_appimage_example", version = "0.0.0") + +bazel_dep(name = "rules_appimage", version = "1.5.0") + +bazel_dep(name = "rules_python", version = "0.27.1") +python = use_extension("@rules_python//python/extensions:python.bzl", "python") +python.toolchain(python_version = "3.11") +pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip") +pip.parse( + hub_name = "py_deps", + python_version = "3.11", + requirements_lock = "requirements.txt", +) +use_repo(pip, "py_deps") diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..b948925d --- /dev/null +++ b/examples/README.md @@ -0,0 +1,7 @@ +# Example Workspace using rules_appimage + +This is a simple example workspace that uses rules_appimage to build an AppImage from a py_binary. + +`BUILD` contains the definition of a `py_binary` target that is wrapped into an AppImage using the `appimage` rule. + +`integration_test.sh` shows how the appimage is built and invoked. diff --git a/examples/hello.py b/examples/hello.py new file mode 100644 index 00000000..b5e0831c --- /dev/null +++ b/examples/hello.py @@ -0,0 +1,18 @@ +"""Example Python application.""" + +from pathlib import Path + +import click + +DATA_FILE = Path("resources/data.txt") + + +@click.command() # type: ignore [misc] +def main() -> None: + """Print "Hello, world!" to the console.""" + data = DATA_FILE.read_text().strip() + click.echo(data) + + +if __name__ == "__main__": + main() diff --git a/examples/integration_test.sh b/examples/integration_test.sh new file mode 100755 index 00000000..07a58f0e --- /dev/null +++ b/examples/integration_test.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +set -euxo pipefail + +bazel build //:hello.appimage + +trap "rm -f hello.appimage" EXIT +cp -f bazel-bin/hello.appimage . + +ls -lah hello.appimage +file hello.appimage + +if ! output="$(./hello.appimage 2>&1)"; then + echo "Unexpected failure: $output" + exit 1 +elif [[ $output != "Hello, World!" ]]; then + echo "Unexpected output: $output" + exit 1 +fi diff --git a/examples/requirements.txt b/examples/requirements.txt new file mode 100644 index 00000000..2f72dd5e --- /dev/null +++ b/examples/requirements.txt @@ -0,0 +1 @@ +click==8.1.7 diff --git a/examples/resources/BUILD b/examples/resources/BUILD new file mode 100644 index 00000000..ead21805 --- /dev/null +++ b/examples/resources/BUILD @@ -0,0 +1,5 @@ +filegroup( + name = "resources", + srcs = ["data.txt"], + visibility = ["//visibility:public"], +) diff --git a/examples/resources/data.txt b/examples/resources/data.txt new file mode 100644 index 00000000..8ab686ea --- /dev/null +++ b/examples/resources/data.txt @@ -0,0 +1 @@ +Hello, World! diff --git a/tests/BUILD b/tests/BUILD index 56e63647..cefc48f0 100644 --- a/tests/BUILD +++ b/tests/BUILD @@ -89,7 +89,8 @@ appimage( name = "appimage_py", binary = ":test_py", build_args = [ - # Example: Compress the squashfs with zstd (gzip is usually the default). + # Example: Compress the squashfs with zstd. mksquashfs defaults to gzip, see + # https://github.com/lalten/rules_appimage/blob/0ba8e8b7f82e69c7aa6dfac62679bb3137ca4b02/third_party/squashfs-tools.BUILD#L10 "-comp", "zstd", ],