Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/act/act-pytest.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
cd "$ROOT"

# act bind-mounts the repo; earlier root steps may leave root-owned __pycache__ dirs.
find "$ROOT" -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true

# Prefer ~/.local/bin/act over an older ~/bin/act install.
export PATH="${HOME}/.local/bin:${PATH}"
hash -r 2>/dev/null || true

DOCKER_GID="$(stat -c '%g' /var/run/docker.sock)"
GITHUB_TOKEN="${GITHUB_TOKEN:-${ghpat:-$(gh auth token 2>/dev/null || true)}}"

if [[ -z "${GITHUB_TOKEN}" ]]; then
echo "Set GITHUB_TOKEN or ghpat before running." >&2
exit 1
fi

ACT_VERSION="$(act --version 2>/dev/null | awk '{print $3}')"
MIN_ACT_VERSION="0.2.81"
if [[ -n "${ACT_VERSION}" ]] \
&& [[ "$(printf '%s\n' "${MIN_ACT_VERSION}" "${ACT_VERSION}" | sort -V | head -1)" != "${MIN_ACT_VERSION}" ]]; then
echo "act ${ACT_VERSION} is too old for node24 actions; install act >= ${MIN_ACT_VERSION}." >&2
echo " curl -sL https://github.com/nektos/act/releases/download/v0.2.89/act_Linux_x86_64.tar.gz | tar -xz -C ~/.local/bin act" >&2
exit 1
fi

# act-latest has no passwordless sudo for ubuntu; run the job as root for apt/sudo steps.
# install.sh re-execs bench setup as ubuntu. Map test_site via docker --add-host below.
ACT_RUNNER_IMAGE="${ACT_RUNNER_IMAGE:-catthehacker/ubuntu:act-latest}"
ACT_PULL_ARGS=(--pull=false)
if ! docker image inspect "${ACT_RUNNER_IMAGE}" >/dev/null 2>&1; then
echo "Runner image ${ACT_RUNNER_IMAGE} not found locally; pulling once..." >&2
ACT_PULL_ARGS=(--pull=true)
fi

# ACT job container shares the service Docker network; use the service hostname.
# GHA runs steps on the VM host and uses 127.0.0.1:1631 from the workflow env instead.
exec act pull_request \
-W .github/workflows/pytest.yaml \
-j tests \
-e .github/act/pull_request.json \
-s "GITHUB_TOKEN=${GITHUB_TOKEN}" \
--actor "$(gh api user -q .login 2>/dev/null || echo nektos)" \
-P "ubuntu-latest=${ACT_RUNNER_IMAGE}" \
"${ACT_PULL_ARGS[@]}" \
--container-architecture linux/amd64 \
--env BENCH_ROOT=/home/ubuntu/frappe-bench \
--env BEAM_TEST_TELEMETRY=true \
--env BEAM_TEST_STACK_DUMP_SECONDS=60 \
--env BEAM_CUPS_HOST=cups \
--env BEAM_CUPS_PORT=631 \
--container-options "--group-add ${DOCKER_GID} --add-host test_site:127.0.0.1" \
"$@"
10 changes: 10 additions & 0 deletions .github/act/pull_request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"pull_request": {
"base": {
"ref": "version-15"
},
"head": {
"ref": "add_printer_wizard"
}
}
}
5 changes: 5 additions & 0 deletions .github/helper/common_site_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"redis_cache": "redis://127.0.0.1:6379",
"redis_queue": "redis://127.0.0.1:6379",
"redis_socketio": "redis://127.0.0.1:6379"
}
40 changes: 35 additions & 5 deletions .github/helper/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,24 @@ export PIP_ROOT_USER_ACTION=ignore

set -e

# act runs workflow steps as root; bench refuses root. Re-run this script as ubuntu.
if [[ "${ACT:-}" == "true" && "$(id -u)" -eq 0 ]]; then
mkdir -p /home/ubuntu
chown ubuntu:ubuntu /home/ubuntu
exec runuser -u ubuntu -- env \
HOME=/home/ubuntu \
ACT=true \
BRANCH_NAME="${BRANCH_NAME:-}" \
GITHUB_WORKSPACE="${GITHUB_WORKSPACE}" \
PIP_ROOT_USER_ACTION=ignore \
PATH="${PATH}" \
bash "$0"
fi

# Check for merge conflicts before proceeding
python -m compileall -f "${GITHUB_WORKSPACE}"
if [[ "${ACT:-}" != "true" ]]; then
python -m compileall -f "${GITHUB_WORKSPACE}"
fi
if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
then echo "Found merge conflicts"
exit 1
Expand All @@ -30,6 +46,8 @@ echo BRANCH_NAME: "${BRANCH_NAME}"
git clone https://github.com/frappe/frappe --branch ${BRANCH_NAME}
bench init frappe-bench --frappe-path ~/frappe --python "$(which python)" --skip-assets --ignore-exist

cp "${GITHUB_WORKSPACE}/.github/helper/common_site_config.json" ~/frappe-bench/sites/common_site_config.json

mkdir ~/frappe-bench/sites/test_site
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/

Expand All @@ -39,6 +57,20 @@ sed -i 's/watch:/# watch:/g' Procfile
sed -i 's/schedule:/# schedule:/g' Procfile
sed -i 's/socketio:/# socketio:/g' Procfile
sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile
sed -i 's/^redis_cache:/# redis_cache:/g' Procfile
sed -i 's/^redis_queue:/# redis_queue:/g' Procfile

wait_for_redis() {
local port="${REDIS_PORT:-6379}"
for _ in $(seq 1 60); do
if (echo > /dev/tcp/127.0.0.1/"$port") 2>/dev/null; then
return 0
fi
sleep 1
done
echo "Redis service did not become reachable on port ${port}" >&2
return 1
}

bench get-app erpnext https://github.com/frappe/erpnext --branch ${BRANCH_NAME} --resolve-deps --skip-assets
bench get-app beam "${GITHUB_WORKSPACE}" --skip-assets
Expand All @@ -47,8 +79,7 @@ printf '%s\n' 'frappe' 'erpnext' 'beam' > ~/frappe-bench/sites/apps.txt
bench setup requirements --python
bench use test_site

bench start &> bench_run_logs.txt &
CI=Yes &
wait_for_redis
bench --site test_site reinstall --yes --admin-password admin

bench setup requirements --dev
Expand All @@ -58,6 +89,5 @@ bench version
echo "SITE LIST-APPS:"
bench list-apps

bench start &> bench_run_logs.txt &
CI=Yes &
wait_for_redis
bench execute 'beam.tests.setup.before_test'
9 changes: 6 additions & 3 deletions .github/helper/install_dependencies.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#!/bin/bash

# Check for merge conflicts before proceeding
python -m compileall -f $GITHUB_WORKSPACE
if grep -lr --exclude-dir=node_modules "^<<<<<<< " $GITHUB_WORKSPACE
if [[ "${ACT:-}" != "true" ]]; then
python -m compileall -f "${GITHUB_WORKSPACE}"
fi
if grep -lr --exclude-dir=node_modules "^<<<<<<< " "${GITHUB_WORKSPACE}"
then echo "Found merge conflicts"
exit 1
fi

sudo apt update -y && sudo apt install redis-server libcups2-dev mariadb-client -y
# redis-server binary is required for `bench init` version detection; runtime Redis is the workflow service.
sudo apt update -y && sudo apt install redis-server cups libcups2-dev mariadb-client cron -y
61 changes: 61 additions & 0 deletions .github/workflows/publish-cups.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Publish CUPS container

on:
push:
branches:
- version-14
- version-15
workflow_dispatch:

env:
REGISTRY: ghcr.io
IMAGE_NAME: agritheory/beam-cups

jobs:
publish:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Resolve CUPS admin credentials
id: creds
env:
CUPS_ADMIN_USER_SECRET: ${{ secrets.CUPS_ADMIN_USER }}
CUPS_ADMIN_PASSWORD_SECRET: ${{ secrets.CUPS_ADMIN_PASSWORD }}
run: |
echo "user=${CUPS_ADMIN_USER_SECRET:-admin}" >> "$GITHUB_OUTPUT"
echo "password=${CUPS_ADMIN_PASSWORD_SECRET:-root}" >> "$GITHUB_OUTPUT"

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest,enable=${{ github.ref_name == 'version-15' }}
type=ref,event=branch
type=sha,prefix=sha-

- name: Build and push
uses: docker/build-push-action@v6
with:
context: cups/cups
file: cups/cups/Containerfile
push: true
build-args: |
CUPS_ADMIN_USER=${{ steps.creds.outputs.user }}
CUPS_ADMIN_PASSWORD=${{ steps.creds.outputs.password }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
96 changes: 91 additions & 5 deletions .github/workflows/pytest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,69 @@ env:
# cancel-in-progress: true

jobs:
build-cups:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
image: ${{ steps.image.outputs.image }}
cups_admin_user: ${{ steps.creds.outputs.user }}
cups_admin_password: ${{ steps.creds.outputs.password }}
steps:
- name: Clone
uses: actions/checkout@v4

- name: Resolve CUPS admin credentials
id: creds
env:
CUPS_ADMIN_USER_SECRET: ${{ secrets.CUPS_ADMIN_USER }}
CUPS_ADMIN_PASSWORD_SECRET: ${{ secrets.CUPS_ADMIN_PASSWORD }}
run: |
echo "user=${CUPS_ADMIN_USER_SECRET:-admin}" >> "$GITHUB_OUTPUT"
echo "password=${CUPS_ADMIN_PASSWORD_SECRET:-root}" >> "$GITHUB_OUTPUT"

- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push CUPS image
id: build
uses: docker/build-push-action@v6
with:
context: cups/cups
file: cups/cups/Containerfile
push: true
build-args: |
CUPS_ADMIN_USER=${{ steps.creds.outputs.user }}
CUPS_ADMIN_PASSWORD=${{ steps.creds.outputs.password }}
tags: ghcr.io/agritheory/beam-cups:sha-${{ github.sha }}

- name: Export image reference
id: image
run: echo "image=ghcr.io/agritheory/beam-cups:sha-${{ github.sha }}" >> "$GITHUB_OUTPUT"

tests:
needs: build-cups
runs-on: ${{ matrix.os }}
permissions:
contents: read
packages: read
pull-requests: write
strategy:
matrix:
os: [ubuntu-latest]
fail-fast: false
name: Server
env:
CUPS_ADMIN_USER: ${{ needs.build-cups.outputs.cups_admin_user }}
CUPS_ADMIN_PASSWORD: ${{ needs.build-cups.outputs.cups_admin_password }}
BEAM_CUPS_HOST: 127.0.0.1
BEAM_CUPS_PORT: "1631"
BENCH_ROOT: /home/runner/frappe-bench

services:
mariadb:
Expand All @@ -33,7 +89,27 @@ jobs:
MYSQL_ROOT_PASSWORD: 'admin'
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
options: --health-cmd="mysqladmin ping -h 127.0.0.1 -uroot -padmin" --health-interval=5s --health-timeout=2s --health-retries=3

redis:
image: redis:7
ports:
- 6379:6379
options: --health-cmd="redis-cli ping" --health-interval=5s --health-timeout=2s --health-retries=3

cups:
image: ${{ needs.build-cups.outputs.image }}
credentials:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
ports:
- 1631:631
options: >-
--add-host=host.docker.internal:host-gateway
--health-cmd="bash -c 'echo > /dev/tcp/127.0.0.1/631'"
--health-interval=5s
--health-timeout=3s
--health-retries=12

steps:
- name: Clone
Expand All @@ -52,6 +128,7 @@ jobs:
cache: 'yarn' # Replaces `Get yarn cache directory path` and `yarn-cache` steps

- name: Add to Hosts
if: ${{ !env.ACT }}
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts

- name: Cache pip
Expand Down Expand Up @@ -81,15 +158,24 @@ jobs:
bash ${{ github.workspace }}/.github/helper/install.sh

- name: Run Tests
working-directory: /home/runner/frappe-bench
working-directory: ${{ env.BENCH_ROOT }}
env:
POETRY_VIRTUALENVS_CREATE: "false"
BEAM_TEST_TELEMETRY: "true"
BEAM_TEST_STACK_DUMP_SECONDS: "60"
run: |
set -o pipefail
source env/bin/activate
cd apps/beam
poetry install
pytest --cov=beam --cov-report=xml --disable-warnings -s | tee pytest-coverage.txt
pytest --cov=beam --cov-report=xml --cov-report=term-missing:skip-covered --disable-warnings -s | tee pytest-coverage.txt

- name: Pytest coverage comment
if: ${{ !env.ACT }}
uses: MishaKav/pytest-coverage-comment@main
with:
pytest-coverage-path: /home/runner/frappe-bench/apps/beam/pytest-coverage.txt
pytest-xml-coverage-path: /home/runner/frappe-bench/apps/beam/coverage.xml
pytest-coverage-path: ${{ env.BENCH_ROOT }}/apps/beam/pytest-coverage.txt
pytest-xml-coverage-path: ${{ env.BENCH_ROOT }}/apps/beam/coverage.xml
default-branch: version-15
report-only-changed-files: true
xml-skip-covered: true
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ repos:
additional_dependencies: ['flake8-bugbear']

- repo: https://github.com/agritheory/test_utils
rev: v1.20.2
rev: v1.28.0
hooks:
- id: update_pre_commit_config
- id: validate_frappe_project
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ mypy ./apps/beam/beam --ignore-missing-imports
pytest ./apps/beam/beam/tests -s --disable-warnings
```

CUPS integration tests (`test_printer_cups_integration.py`) use the CUPS service container from the pytest workflow (built from [`cups/cups/Containerfile`](./cups/cups/Containerfile)). Locally, publish port 631 from the beam-cups image and set `BEAM_CUPS_HOST` / `BEAM_CUPS_PORT`.

### Printer Server setup
```shell
sudo apt-get install gcc cups python3-dev libcups2-dev -y
Expand Down
Loading
Loading