Skip to content

Commit

Permalink
feat: support for multi os (#21)
Browse files Browse the repository at this point in the history
Signed-off-by: amannocci <[email protected]>
  • Loading branch information
amannocci authored Apr 22, 2024
1 parent cd0f331 commit 3b5755f
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 61 deletions.
55 changes: 38 additions & 17 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,42 +1,63 @@
---

name: CI

on:
pull_request:
branches:
- main
push:
branches:
- main

permissions:
contents: read

## Concurrency only allowed in the main branch.
## So old builds running for old commits within the same Pull Request are cancelled
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}

jobs:
test:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- uses: actions/checkout@v4

- name: Install python
uses: actions/setup-python@v4
with:
python-version-file: '.python-version'

- name: Install poetry
run: |
curl -sSL https://install.python-poetry.org | python3 -
poetry install --no-interaction
- name: Setup environment
uses: ./.github/workflows/env-setup

- name: Lint
run: poetry run poe lint

build:
needs:
- lint
strategy:
matrix:
os:
- macos-14
- macos-13
- ubuntu-latest
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Setup environment
uses: ./.github/workflows/env-setup

- name: Build
run: poetry run poe build

test:
needs:
- build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup environment
uses: ./.github/workflows/env-setup

- name: Test
run: poetry run poe test
23 changes: 23 additions & 0 deletions .github/workflows/env-setup/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: env-setup
description: Setup environment

runs:
using: "composite"
steps:
- name: Set up QEMU
if: matrix.os == 'ubuntu-latest'
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: matrix.os == 'ubuntu-latest'
uses: docker/setup-buildx-action@v3

- uses: actions/setup-python@v5
with:
python-version-file: ".python-version"

- name: Install poetry and dependencies
run: |
pip3 install --no-cache-dir --upgrade pip poetry
poetry install --no-interaction
shell: "bash"
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.11.6
3.11.9
22 changes: 10 additions & 12 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
# Base image for build
ARG base_image_version=3.10.12
FROM python:${base_image_version}-bullseye as builder
FROM python:${base_image_version}-slim-bullseye as builder

# Switch workdir
WORKDIR /opt/temply

# Arguments
ARG platform_arch
ARG app_version

# Copy files
COPY . .

# Install build packages
RUN \
apt-get update > /dev/null \
&& apt-get install -y --no-install-recommends \
binutils="*" \
&& apt-get clean

# Install poetry
ENV \
PATH="/opt/poetry/bin:${PATH}" \
POETRY_HOME=/opt/poetry \
POETRY_VIRTUALENVS_CREATE=false
RUN \
curl -sSL https://install.python-poetry.org | python3 -
pip3 install --no-cache-dir --upgrade pip poetry

# Build
RUN \
poetry install \
&& poetry run pyinstaller temply.spec \
&& mv /opt/temply/dist/temply /opt/temply/dist/temply-${app_version}-${platform_arch}
&& poetry run pyinstaller temply.spec
86 changes: 59 additions & 27 deletions scripts/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from pathlib import Path
from time import time

from sh import git, podman
from sh import git, pyinstaller

from scripts.utils import Constants, container_backend, read_project_conf
from scripts.utils import Constants, container_backend, fatal, read_project_conf


def run() -> None:
Expand All @@ -20,29 +20,61 @@ def run() -> None:
# Create dist dir
local_dist_path = Path("dist")
local_dist_path.mkdir(parents=True, exist_ok=False)
local_dist_path = local_dist_path.absolute().as_posix()
local_dist_path = local_dist_path.absolute()

cmd = container_backend()
for platform_arch in ["linux/amd64", "linux/arm64"]:
platform_arch_slug = platform_arch.replace("/", "-")
cmd(
"buildx",
"build",
"--platform",
platform_arch,
"-v",
f"{local_dist_path}:/opt/temply/dist",
"--build-arg",
f"base_image_version={python_version}",
"--build-arg",
f"platform_arch={platform_arch_slug}",
"--build-arg",
f"app_version={version}",
"-t",
f"{Constants.REGISTRY_URL}/temply:{image_id}",
"-f",
"Containerfile",
".",
_out=sys.stdout,
_err=sys.stderr,
)
system = platform.system().lower()
if system == "darwin":
pyinstaller("temply.spec", _out=sys.stdout, _err=sys.stderr)
arch = platform.machine()
arch = "amd64" if arch == "x86_64" else arch
Path("./dist/temply").replace(Path(f"./dist/temply-{version}-{system}-{arch}"))
elif system == "linux":
# Use cross-build to build both amd64 and arm64 versions.
cmd, env = container_backend()
for arch in ["amd64", "arm64"]:
platform_arch = f"linux/{arch}"
cmd(
"buildx",
"build",
"--load",
"--platform",
platform_arch,
"--build-arg",
f"base_image_version={python_version}",
"-t",
f"{Constants.REGISTRY_URL}/temply:{image_id}",
"-f",
"Containerfile",
".",
_out=sys.stdout,
_err=sys.stderr,
_env=env,
)
container_id = cmd(
"run",
"-d",
"--platform",
platform_arch,
"--entrypoint=cat",
f"{Constants.REGISTRY_URL}/temply:{image_id}",
_err=sys.stderr,
_env=env,
).strip()
cmd(
"cp",
f"{container_id}:/opt/temply/dist/temply",
(local_dist_path / f"temply-{version}-linux-{arch}").as_posix(),
_out=sys.stdout,
_err=sys.stderr,
_env=env,
)
cmd(
"rm",
"-f",
container_id,
_out=sys.stdout,
_err=sys.stderr,
_env=env,
)
else:
fatal(f"Unsupported system: {system}")
11 changes: 7 additions & 4 deletions scripts/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def detect_poetry() -> Command:
fatal("`poetry` isn't detected")


def container_backend() -> Command:
def container_backend() -> tuple[Command, dict[str, str]]:
"""
Try to detect a container backend.
Either podman or docker.
Expand All @@ -65,13 +65,16 @@ def container_backend() -> Command:
CommandNotFound: if a suitable backend can't be found.
"""
cmd = None
env = os.environ.copy()
for backend in ["docker", "podman"]:
try:
cmd = Command(backend)
continue
except CommandNotFound:
pass
continue
if "podman" == backend:
env["BUILDAH_FORMAT"] = "docker"
break

if not cmd:
raise CommandNotFound("Unable to find a suitable backend: docker or podman")
return cmd
return cmd, env

0 comments on commit 3b5755f

Please sign in to comment.