snapshot of https://github.com/frappe/crm.git (develop, 2026-09-18; blobs > 131072B omitted)
Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1m13s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 6s
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
Some checks failed
Frontend / Unit Tests & Coverage (push) Has been skipped
Regenerate POT file (translatable strings) / Regenerate POT file (develop) (push) Failing after 1m13s
Regenerate POT file (translatable strings) / Regenerate POT file (main-hotfix) (push) Failing after 6s
Server / Tests (frappe ${{ matrix.frappe-branch }}) (push) Has been skipped
Server / Resolve frappe matrix (push) Failing after 1s
Frontend / Lint (push) Failing after 1s
Frontend / Production Build (push) Failing after 1s
Server / Coverage Wrap Up (push) Has been skipped
Frontend / Coverage Wrap Up (push) Has been skipped
This commit is contained in:
65
.github/workflows/builds.yml
vendored
Normal file
65
.github/workflows/builds.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
name: Build Container Image
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
arch: [amd64, arm64]
|
||||
|
||||
steps:
|
||||
- name: Checkout Entire Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
with:
|
||||
platforms: linux/${{ matrix.arch }}
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set Branch
|
||||
run: |
|
||||
export APPS_JSON='[{"url": "https://github.com/frappe/crm","branch": "main"}]'
|
||||
echo "APPS_JSON_BASE64=$(echo $APPS_JSON | base64 -w 0)" >> $GITHUB_ENV
|
||||
echo "FRAPPE_BRANCH=version-15" >> $GITHUB_ENV
|
||||
|
||||
- name: Set Image Tag
|
||||
run: |
|
||||
echo "IMAGE_TAG=stable" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
repository: frappe/frappe_docker
|
||||
path: builds
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
push: true
|
||||
context: builds
|
||||
file: builds/images/layered/Containerfile
|
||||
tags: >
|
||||
ghcr.io/${{ github.repository }}:${{ github.ref_name }},
|
||||
ghcr.io/${{ github.repository }}:${{ env.IMAGE_TAG }}
|
||||
build-args: |
|
||||
"FRAPPE_BRANCH=${{ env.FRAPPE_BRANCH }}"
|
||||
"APPS_JSON_BASE64=${{ env.APPS_JSON_BASE64 }}"
|
||||
125
.github/workflows/frontend-tests.yml
vendored
Normal file
125
.github/workflows/frontend-tests.yml
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
name: Frontend
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "**.py"
|
||||
- "**.txt"
|
||||
- "**.csv"
|
||||
- "**.po"
|
||||
- "**.pot"
|
||||
- ".github/workflows/server-tests.yml"
|
||||
- ".github/workflows/builds.yml"
|
||||
schedule:
|
||||
# Run every day at midnight UTC / 5:30 IST
|
||||
- cron: "0 0 * * *"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: frontend-${{ github.event.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# frontend/package.json links `@framework/ui` to a sibling frappe checkout
|
||||
# (link:../../frappe/ui); without it, anything importing from @framework/ui
|
||||
# fails to resolve. actions/checkout cannot place a repo outside the
|
||||
# workspace, and only the `ui` package is needed.
|
||||
- name: Clone frappe for @framework/ui
|
||||
run: |
|
||||
git clone --depth 1 --branch develop --filter=blob:none --sparse \
|
||||
https://github.com/frappe/frappe "$GITHUB_WORKSPACE/../frappe"
|
||||
git -C "$GITHUB_WORKSPACE/../frappe" sparse-checkout set ui
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: yarn
|
||||
cache-dependency-path: frontend/yarn.lock
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd frontend && yarn install --frozen-lockfile
|
||||
|
||||
- name: ESLint
|
||||
run: cd frontend && npx eslint src --ext .js,.ts,.vue
|
||||
|
||||
- name: Oxlint
|
||||
run: cd frontend && npx oxlint src
|
||||
|
||||
build:
|
||||
name: Production Build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# see the lint job: @framework/ui links to a sibling frappe checkout
|
||||
- name: Clone frappe for @framework/ui
|
||||
run: |
|
||||
git clone --depth 1 --branch develop --filter=blob:none --sparse \
|
||||
https://github.com/frappe/frappe "$GITHUB_WORKSPACE/../frappe"
|
||||
git -C "$GITHUB_WORKSPACE/../frappe" sparse-checkout set ui
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: yarn
|
||||
cache-dependency-path: frontend/yarn.lock
|
||||
|
||||
- name: Install dependencies
|
||||
run: cd frontend && yarn install --frozen-lockfile
|
||||
|
||||
- name: Build frontend
|
||||
run: cd frontend && yarn build
|
||||
|
||||
test:
|
||||
name: Unit Tests & Coverage
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "24"
|
||||
cache: yarn
|
||||
cache-dependency-path: frontend/yarn.lock
|
||||
|
||||
- name: Run frontend tests
|
||||
uses: ./.github/actions/frontend-tests
|
||||
with:
|
||||
node-version: "24"
|
||||
enable-coverage: "true"
|
||||
|
||||
- name: Upload coverage artifact
|
||||
if: github.base_ref == 'develop' || github.ref_name == 'develop'
|
||||
uses: ./.github/actions/upload-coverage
|
||||
with:
|
||||
artifact-name: coverage-frontend
|
||||
coverage-path: frontend/coverage/lcov.info
|
||||
|
||||
coverage:
|
||||
name: Coverage Wrap Up
|
||||
needs: test
|
||||
if: github.base_ref == 'develop' || github.ref_name == 'develop'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Publish coverage to Codecov
|
||||
uses: ./.github/actions/publish-codecov
|
||||
with:
|
||||
name: Frontend
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
40
.github/workflows/generate-pot-file.yml
vendored
Normal file
40
.github/workflows/generate-pot-file.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
name: Regenerate POT file (translatable strings)
|
||||
on:
|
||||
schedule:
|
||||
# 9:30 UTC => 3 PM IST Sunday
|
||||
- cron: "30 9 * * 0"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
regenerate-pot-file:
|
||||
name: Regenerate POT file
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
branch: ["develop", "main-hotfix"]
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ matrix.branch }}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.14"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Run script to update POT file
|
||||
run: |
|
||||
bash ${GITHUB_WORKSPACE}/.github/helper/update_pot_file.sh
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
BASE_BRANCH: ${{ matrix.branch }}
|
||||
85
.github/workflows/linters.yml
vendored
Normal file
85
.github/workflows/linters.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
name: Linters
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
jobs:
|
||||
commit-lint:
|
||||
name: Semantic Commits
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 200
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "24"
|
||||
check-latest: true
|
||||
|
||||
- name: Install commitlint
|
||||
run: npm install --no-save @commitlint/cli @commitlint/config-conventional
|
||||
|
||||
- name: Check commit titles
|
||||
run: npx commitlint --verbose --from "${{ github.event.pull_request.base.sha }}" --to "${{ github.event.pull_request.head.sha }}"
|
||||
|
||||
semgrep:
|
||||
name: Semgrep Rules
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
||||
PYTHONDONTWRITEBYTECODE: "1"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
cache: pip
|
||||
|
||||
- name: Install Semgrep
|
||||
run: pip install --upgrade semgrep
|
||||
|
||||
- name: Download Semgrep rules
|
||||
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||
|
||||
- name: Run Semgrep rules
|
||||
run: semgrep ci --config ./frappe-semgrep-rules/rules --config r/python.lang.correctness
|
||||
|
||||
pre-commit:
|
||||
name: Pre-commit Checks
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
PIP_DISABLE_PIP_VERSION_CHECK: "1"
|
||||
PYTHONDONTWRITEBYTECODE: "1"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
cache: pip
|
||||
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Install frontend dependencies
|
||||
run: cd frontend && yarn install
|
||||
|
||||
- name: Run Pre-commit
|
||||
uses: pre-commit/action@v3.0.1
|
||||
with:
|
||||
extra_args: --all-files
|
||||
107
.github/workflows/migration-test.yml
vendored
Normal file
107
.github/workflows/migration-test.yml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
name: Migration
|
||||
|
||||
# Verifies that an existing site on the PR's base branch can `bench migrate`
|
||||
# to the PR code. Catches broken patches / schema changes before release.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.css"
|
||||
- "**.js"
|
||||
- "**.md"
|
||||
- "**.html"
|
||||
- "**.csv"
|
||||
- "**.po"
|
||||
- "**.pot"
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: migration-${{ github.event.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
migrate:
|
||||
name: Upgrade base branch -> PR
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10.6
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
env:
|
||||
BASE_BRANCH: ${{ github.base_ref || github.ref_name }}
|
||||
BENCH_PATH: /home/runner/frappe-bench
|
||||
|
||||
steps:
|
||||
- name: Checkout PR code
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: pr-crm
|
||||
|
||||
- name: Resolve frappe branch for base
|
||||
id: frappe
|
||||
run: |
|
||||
# Stable lanes run on frappe version-15; develop tracks frappe develop.
|
||||
case "$BASE_BRANCH" in
|
||||
main|main-hotfix) echo "branch=version-15" >> "$GITHUB_OUTPUT" ;;
|
||||
*) echo "branch=develop" >> "$GITHUB_OUTPUT" ;;
|
||||
esac
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
with:
|
||||
python-version: "3.14"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "24"
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y libcups2-dev redis-server mariadb-client libmariadb-dev
|
||||
npm install -g yarn
|
||||
|
||||
- name: Configure database
|
||||
run: |
|
||||
echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
|
||||
|
||||
- name: Init bench with frappe
|
||||
run: |
|
||||
pip install frappe-bench
|
||||
git clone "https://github.com/frappe/frappe" --branch "${{ steps.frappe.outputs.branch }}" --depth 1 ~/frappe
|
||||
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" "$BENCH_PATH"
|
||||
|
||||
- name: Install CRM at base branch
|
||||
working-directory: /home/runner/frappe-bench
|
||||
run: |
|
||||
mkdir sites/test_site
|
||||
cp "${GITHUB_WORKSPACE}/pr-crm/.github/helper/site_config.json" sites/test_site/site_config.json
|
||||
sed -i 's/watch:/# watch:/g; s/schedule:/# schedule:/g; s/socketio:/# socketio:/g; s/redis_socketio:/# redis_socketio:/g' Procfile
|
||||
bench get-app crm "https://github.com/frappe/crm" --branch "$BASE_BRANCH"
|
||||
bench setup requirements --dev
|
||||
bench start &>> "$BENCH_PATH/bench_start.log" &
|
||||
CI=Yes bench build --app frappe &
|
||||
bench --site test_site reinstall --yes
|
||||
bench --verbose --site test_site install-app crm
|
||||
|
||||
- name: Upgrade CRM to PR code and migrate
|
||||
working-directory: /home/runner/frappe-bench
|
||||
run: |
|
||||
# Swap the installed (base branch) code for the PR code, keep the git dir.
|
||||
rsync -a --delete --exclude=".git" "${GITHUB_WORKSPACE}/pr-crm/" apps/crm/
|
||||
bench setup requirements --dev
|
||||
bench --site test_site migrate
|
||||
32
.github/workflows/on_release.yml
vendored
Normal file
32
.github/workflows/on_release.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Generate Semantic Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Entire Repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
npm install @semantic-release/git @semantic-release/exec --no-save
|
||||
- name: Create Release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
GIT_AUTHOR_NAME: "Frappe PR Bot"
|
||||
GIT_AUTHOR_EMAIL: "developers@frappe.io"
|
||||
GIT_COMMITTER_NAME: "Frappe PR Bot"
|
||||
GIT_COMMITTER_EMAIL: "developers@frappe.io"
|
||||
run: npx semantic-release
|
||||
40
.github/workflows/release_notes.yml
vendored
Normal file
40
.github/workflows/release_notes.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# This action:
|
||||
#
|
||||
# 1. Generates release notes using github API.
|
||||
# 2. Strips unnecessary info like chore/style etc from notes.
|
||||
# 3. Updates release info.
|
||||
|
||||
name: 'Release Notes'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag_name:
|
||||
description: 'Tag of release like v1.0.0'
|
||||
required: true
|
||||
type: string
|
||||
release:
|
||||
types: [released]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
regen-notes:
|
||||
name: 'Regenerate release notes'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update notes
|
||||
run: |
|
||||
NEW_NOTES=$(gh api --method POST -H "Accept: application/vnd.github+json" /repos/frappe/crm/releases/generate-notes -f tag_name=$RELEASE_TAG \
|
||||
| jq -r '.body' \
|
||||
| sed -E '/^\* (chore|ci|test|docs|style)/d' \
|
||||
| sed -E 's/by @mergify //'
|
||||
)
|
||||
RELEASE_ID=$(gh api -H "Accept: application/vnd.github+json" /repos/frappe/crm/releases/tags/$RELEASE_TAG | jq -r '.id')
|
||||
gh api --method PATCH -H "Accept: application/vnd.github+json" /repos/frappe/crm/releases/$RELEASE_ID -f body="$NEW_NOTES"
|
||||
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
RELEASE_TAG: ${{ github.event.inputs.tag_name || github.event.release.tag_name }}
|
||||
106
.github/workflows/server-tests.yml
vendored
Normal file
106
.github/workflows/server-tests.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
name: Server
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- "**.css"
|
||||
- "**.js"
|
||||
- "**.md"
|
||||
- "**.html"
|
||||
- "**.csv"
|
||||
- "**.po"
|
||||
- "**.pot"
|
||||
schedule:
|
||||
# Run everday at midnight UTC / 5:30 IST
|
||||
- cron: "0 0 * * *"
|
||||
env:
|
||||
CRM_BRANCH: ${{ github.base_ref || github.ref_name }}
|
||||
|
||||
concurrency:
|
||||
group: develop-crm-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
name: Resolve frappe matrix
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
frappe-branches: ${{ steps.resolve.outputs.branches }}
|
||||
steps:
|
||||
- name: Resolve frappe branches from target branch
|
||||
id: resolve
|
||||
run: |
|
||||
BASE="${{ github.base_ref || github.ref_name }}"
|
||||
# develop tracks frappe develop; the stable lane ships frappe 15 and 16.
|
||||
if [ "$BASE" = "develop" ]; then
|
||||
echo 'branches=["develop"]' >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo 'branches=["version-15","version-16"]' >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
test:
|
||||
name: Tests (frappe ${{ matrix.frappe-branch }})
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
frappe-branch: ${{ fromJson(needs.setup.outputs.frappe-branches) }}
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10.6
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Setup environment
|
||||
uses: ./.github/actions/setup-server-env
|
||||
with:
|
||||
python-version: "3.14"
|
||||
node-version: "24"
|
||||
type: "server"
|
||||
# erpnext: stable lane only, never v16 (v16 test bootstrap broken on bare bench)
|
||||
install-erpnext: ${{ (github.base_ref == 'main-hotfix' || github.base_ref == 'main') && matrix.frappe-branch != 'version-16' }}
|
||||
frappe-branch: ${{ matrix.frappe-branch }}
|
||||
|
||||
- name: Run server tests
|
||||
uses: ./.github/actions/run-server-tests
|
||||
with:
|
||||
bench-path: "/home/runner/frappe-bench"
|
||||
site: "test_site"
|
||||
app: "crm"
|
||||
enable-coverage: "true"
|
||||
type: "server"
|
||||
ci-build-id: ${{ github.run_id }}
|
||||
|
||||
- name: Persist coverage artifact
|
||||
if: github.base_ref == 'develop' || github.ref_name == 'develop'
|
||||
uses: ./.github/actions/upload-coverage
|
||||
with:
|
||||
artifact-name: coverage-${{ matrix.frappe-branch }}
|
||||
coverage-path: /home/runner/frappe-bench/sites/coverage.xml
|
||||
|
||||
coverage:
|
||||
name: Coverage Wrap Up
|
||||
needs: test
|
||||
if: github.base_ref == 'develop' || github.ref_name == 'develop'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- name: Publish coverage
|
||||
uses: ./.github/actions/publish-codecov
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
181
.github/workflows/ui-tests.yml
vendored
Normal file
181
.github/workflows/ui-tests.yml
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
name: UI Tests
|
||||
|
||||
# E2E (Playwright) suite. Heavy gate: runs on the main-hotfix staging lane
|
||||
# before promoting to main, plus on demand. Develop stays on the fast lane.
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main-hotfix
|
||||
pull_request:
|
||||
branches:
|
||||
- main-hotfix
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ui-tests-crm-${{ github.event.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
FRAPPE_BRANCH: develop
|
||||
|
||||
jobs:
|
||||
ui-tests:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 60
|
||||
name: Playwright E2E Tests
|
||||
|
||||
services:
|
||||
redis-cache:
|
||||
image: redis:alpine
|
||||
ports:
|
||||
- 13000:6379
|
||||
redis-queue:
|
||||
image: redis:alpine
|
||||
ports:
|
||||
- 11000:6379
|
||||
mariadb:
|
||||
image: mariadb:10.6
|
||||
env:
|
||||
MYSQL_ROOT_PASSWORD: root
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
check-latest: true
|
||||
|
||||
- name: Add to Hosts
|
||||
run: echo "127.0.0.1 crm.test" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: 'echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT'
|
||||
|
||||
- name: Cache yarn
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Cache Playwright browsers
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cache/ms-playwright
|
||||
key: ${{ runner.os }}-playwright-${{ hashFiles('package.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-playwright-
|
||||
|
||||
- name: Install MariaDB Client
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install mariadb-client
|
||||
|
||||
- name: Setup Bench
|
||||
run: |
|
||||
pip install frappe-bench
|
||||
bench init --skip-redis-config-generation --skip-assets --frappe-branch "$FRAPPE_BRANCH" --python "$(which python)" ~/frappe-bench
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
mariadb --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
|
||||
- name: Install CRM
|
||||
working-directory: /home/runner/frappe-bench
|
||||
run: |
|
||||
bench get-app crm $GITHUB_WORKSPACE
|
||||
bench setup requirements --dev
|
||||
bench new-site --db-root-password root --admin-password admin crm.test
|
||||
bench --site crm.test install-app crm
|
||||
bench build --app crm
|
||||
env:
|
||||
CI: "Yes"
|
||||
|
||||
- name: Configure Site for UI Tests
|
||||
working-directory: /home/runner/frappe-bench
|
||||
run: |
|
||||
bench --site crm.test set-config allow_tests true
|
||||
bench --site crm.test set-config host_name "http://crm.test:8000"
|
||||
# Dummy default-outgoing account so send-email queues without real SMTP.
|
||||
bench --site crm.test console <<'PY'
|
||||
import frappe
|
||||
if not frappe.db.exists("Email Account", {"default_outgoing": 1}):
|
||||
frappe.get_doc({
|
||||
"doctype": "Email Account",
|
||||
"email_account_name": "E2E Outgoing",
|
||||
"email_id": "e2e@example.com",
|
||||
"smtp_server": "localhost",
|
||||
"smtp_port": 25,
|
||||
"enable_outgoing": 1,
|
||||
"default_outgoing": 1,
|
||||
"no_smtp_authentication": 1,
|
||||
}).insert(ignore_permissions=True)
|
||||
frappe.db.commit()
|
||||
PY
|
||||
|
||||
- name: Start Frappe Server
|
||||
working-directory: /home/runner/frappe-bench
|
||||
run: |
|
||||
sed -i 's/^watch:/# watch:/g' Procfile
|
||||
sed -i 's/^schedule:/# schedule:/g' Procfile
|
||||
bench start &> bench_start.log &
|
||||
echo "Waiting for Frappe server to start..."
|
||||
timeout 60 bash -c 'until curl -s http://crm.test:8000 > /dev/null; do sleep 2; done'
|
||||
echo "Frappe server is ready!"
|
||||
|
||||
- name: Install Playwright
|
||||
run: |
|
||||
npm install --ignore-scripts
|
||||
npx playwright install --with-deps chromium
|
||||
|
||||
- name: Run Playwright Tests
|
||||
run: npx playwright test
|
||||
env:
|
||||
BASE_URL: http://crm.test:8000
|
||||
FRAPPE_USER: Administrator
|
||||
FRAPPE_PASSWORD: admin
|
||||
|
||||
- name: Upload Playwright Report
|
||||
uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 7
|
||||
|
||||
- name: Upload Test Results
|
||||
uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: test-results
|
||||
path: test-results/
|
||||
retention-days: 7
|
||||
|
||||
- name: Show Bench Logs on Failure
|
||||
if: failure()
|
||||
working-directory: /home/runner/frappe-bench
|
||||
run: |
|
||||
echo "=== Bench Start Log ==="
|
||||
cat bench_start.log || true
|
||||
echo ""
|
||||
echo "=== Frappe Logs ==="
|
||||
cat logs/*.log || true
|
||||
Reference in New Issue
Block a user