Zillowe FoundationZillowe Documentation

Package Examples

A set of `.pkg.lua` examples for creating Zoi packages.

This document provides a set of examples for creating .pkg.lua files. These files are the core of Zoi's packaging system, defining everything from metadata to installation methods using the power of Lua scripting.

Simple Pre-compiled Binary

This example shows how to package a simple pre-compiled binary that is downloaded from a URL (like a GitHub release). It's for a hypothetical tool called my-cli.

-- my-cli.pkg.lua
metadata({
  name = "my-cli",
  repo = "community",
  version = "1.2.3",
  description = "A cool command-line tool.",
  website = "https://example.com/my-cli",
  license = "MIT",
  bins = { "my-cli" },
  types = { "pre-compiled" },
})

function prepare()
  local version = PKG.version
  local os = SYSTEM.OS
  local arch = SYSTEM.ARCH
  local ext = "tar.gz"
  if os == "windows" then
    ext = "zip"
  end

  -- Construct the download URL, e.g. from GitHub releases
  local url = "https://example.com/my-cli/releases/download/v" .. version .. "/my-cli-" .. os .. "-" .. arch .. "." .. ext

  -- Download and extract the archive into a directory named "extracted_cli" inside the temporary build directory
  UTILS.EXTRACT(url, "extracted_cli")
end

function package()
  local bin_name = "my-cli"
  if SYSTEM.OS == "windows" then
    bin_name = "my-cli.exe"
  end

  -- Copy the binary from the extracted directory to the package store.
  -- ${pkgstore} is a special variable that points to the final installation directory for the package.
  zcp("extracted_cli/" .. bin_name, "${pkgstore}/bin/" .. bin_name)
end

Bundling a Local Asset

This example shows how to use the ${pkgluadir} variable to bundle a file that is located in the same directory as your .pkg.lua file.

Assume you have the following file structure:

my-package/
├── my-package.pkg.lua
└── icon.png
-- my-package.pkg.lua
metadata({
  name = "my-package-with-asset",
  repo = "community",
  version = "1.0.0",
  description = "A package that bundles a local asset.",
  license = "MIT",
  types = { "source" },
})

function package()
  -- Copy the icon.png from the same directory as the pkg.lua file
  -- into the package's shared data directory.
  zcp("${pkgluadir}/icon.png", "${pkgstore}/share/icons/my-package.png")
end

Simple Source Build

This example shows how to build a package from source. It clones a git repository and runs make to build the binary.

-- my-git-tool.pkg.lua
metadata({
  name = "my-git-tool",
  repo = "community",
  version = "1.0.0",
  description = "A simple tool built from a git repository.",
  website = "https://example.com/my-git-tool",
  license = "GPL-3.0-or-later",
  bins = { "my-git-tool" },
  types = { "source" },
})

-- Define build-time dependencies. Zoi will ensure these are available.
dependencies({
  build = {
    required = { "native:gcc", "native:make", "native:git" }
  }
})

function prepare()
  -- Clone the git repository into a "source" directory inside the temporary build directory
  cmd("git clone https://example.com/my-git-tool.git source")
end

function package()
  -- Run build commands inside the cloned repository
  cmd("cd source && make")

  -- Copy the final binary to the package store
  zcp("source/my-git-tool", "${pkgstore}/bin/my-git-tool")
end

Advanced Example

This example, based on the real hello package from the zillowe repository, demonstrates more advanced features like platform mapping, checksum and signature verification, and handling both pre-compiled and source builds in one file.

local repo_owner = "Zillowe"
local repo_name = "Hello"
local version = ZOI.VERSION or "3.0.0"
local git_url = "https://github.com/" .. repo_owner .. "/" .. repo_name .. ".git"
local release_base_url = "https://github.com/" .. repo_owner .. "/" .. repo_name .. "/releases/download/v" .. version

local platform_map = {
  macos = "darwin",
}

local function get_mapped_platform()
  local current_platform = SYSTEM.OS .. "-" .. SYSTEM.ARCH
  return platform_map[current_platform] or platform_map[SYSTEM.OS] or current_platform
end

local function get_mapped_os()
  return get_mapped_platform():match("([^-]+)")
end

metadata({
  name = "hello",
  repo = "zillowe",
  version = version,
  description = "Hello World",
  website = "https://github.com/Zillowe/Hello",
  git = git_url,
  man = "https://raw.githubusercontent.com/Zillowe/Hello/refs/heads/main/app/man.md",
  maintainer = {
    name = "Zillowe Foundation",
    website = "https://zillowe.qzz.io",
    email = "[email protected]",
  },
  author = {
    name = "Zillowe Foundation",
    website = "https://zillowe.qzz.io",
    email = "[email protected]",
  },
  license = "Apache-2.0",
  bins = { "hello" },
  conflicts = { "hello" },
  types = { "source", "pre-compiled" },
})

dependencies({
  build = {
    types = {
      source = {
        required = { "native:zig" },
      }
    }
  },
})

function prepare()
  print("Adding PGP key for verification...")
  addPgpKey("https://zillowe.pages.dev/keys/zillowe-main.asc", "zillowe-main")

  if BUILD_TYPE == "pre-compiled" then
    local ext
    if SYSTEM.OS == "windows" then
      ext = "zip"
    else
      ext = "tar.xz"
    end
    local file_name = "hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH .. "." .. ext
    local url = release_base_url .. "/" .. file_name

    UTILS.EXTRACT(url, "precompiled")
  elseif BUILD_TYPE == "source" then
    cmd("git clone " .. PKG.git .. " " .. BUILD_DIR .. "/source")
    cmd("cd " .. BUILD_DIR .. "/source && zig build-exe main.zig -O ReleaseSmall --name hello")
  end
end

function package()
  local bin_name = "hello"
  if SYSTEM.OS == "windows" then
    bin_name = "hello.exe"
  end

  if BUILD_TYPE == "pre-compiled" then
    local bin_path = UTILS.FIND.file("precompiled", bin_name)
    if bin_path then
      zcp(bin_path, "${pkgstore}/bin/" .. bin_name)
    else
      error("Could not find '" .. bin_name .. "' in pre-compiled archive.")
    end
  elseif BUILD_TYPE == "source" then
    zcp("source/" .. bin_name, "${pkgstore}/bin/" .. bin_name)
  end
end

function verify()
  if BUILD_TYPE == "pre-compiled" then
    local checksum_url = release_base_url .. "/checksums-512.txt"
    local checksum_content = UTILS.FETCH.url(checksum_url)

    local ext
    if SYSTEM.OS == "windows" then
      ext = "zip"
    else
      ext = "tar.xz"
    end
    local file_name = "hello-" .. get_mapped_os() .. "-" .. SYSTEM.ARCH .. "." .. ext
    local file_path = BUILD_DIR .. "/" .. file_name

    local expected_checksum = UTILS.PARSE.checksumFile(checksum_content, file_name)

    if not expected_checksum or not verifyHash(file_path, "sha512-" .. expected_checksum) then
      print("Checksum verification failed!")
      return false
    end
    print("Checksum verified successfully.")

    print("Verifying signature...")
    local sig_url = release_base_url .. "/" .. file_name .. ".sig"
    local sig_path = BUILD_DIR .. "/" .. file_name .. ".sig"

    print("Downloading signature from " .. sig_url)
    UTILS.FILE(sig_url, sig_path)

    if not verifySignature(file_path, sig_path, "zillowe-main") then
      print("Signature verification failed!")
      return false
    end

    print("Signature verified successfully.")
    return true
  end
  return true
end

function uninstall() end

Last updated on