From 442d9485aceb5e171b8db055ca61ad4631107809 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 29 Apr 2026 13:23:42 -0700 Subject: [PATCH 01/21] Run trivy scanner --- .github/workflows/deploy-pm4.yml | 38 ++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 61137d9..6e984f7 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -70,18 +70,6 @@ jobs: - name: List Images run: | docker images - # - name: Run Trivy vulnerability scanner - # uses: aquasecurity/trivy-action@master - # with: - # image-ref: processmaker/enterprise:${{ env.VERSION }} - # format: 'table' - # exit-code: '0' - # ignore-unfixed: false - # vuln-type: 'os,library' - # scanners: 'vuln,secret' - # severity: 'MEDIUM,HIGH,CRITICAL' - # env: - # TRIVY_TIMEOUT: 30m - name: Login to Harbor uses: docker/login-action@v2 with: @@ -429,3 +417,29 @@ jobs: -Dsonar.tests=. -Dsonar.test.inclusions=**/*Test.php -Dsonar.php.coverage.reportPaths=./pm4-k8s-distribution/images/pm4-tools/coverage.xml + + trivyScan: + name: Trivy vulnerability scan + # if: github.event.action != 'closed' && inputs.delete == '' && !contains(github.event.pull_request.body, 'ci:skip-build') + needs: imageEKS + runs-on: ${{ vars.RUNNER }} + steps: + - name: Login to Harbor + uses: docker/login-action@v2 + with: + registry: ${{ secrets.REGISTRY_HOST }} + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + + - name: Run Trivy vulnerability scanner + uses: aquasecurity/trivy-action@v0.36.0 + with: + image-ref: ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{ env.IMAGE_TAG }} + format: table + exit-code: '0' + ignore-unfixed: false + vuln-type: os,library + scanners: vuln,secret + severity: MEDIUM,HIGH,CRITICAL + env: + TRIVY_TIMEOUT: 30m From 2bb2a69c493c1d6d286cc4a50fe2ec694050722c Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 29 Apr 2026 14:33:37 -0700 Subject: [PATCH 02/21] Fix image tag name --- .github/workflows/deploy-pm4.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 6e984f7..0798604 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -424,6 +424,9 @@ jobs: needs: imageEKS runs-on: ${{ vars.RUNNER }} steps: + - name: Set Image Tag + run: | + echo "RESOLVED_IMAGE_TAG=${{ env.IMAGE_TAG }}" >> $GITHUB_ENV - name: Login to Harbor uses: docker/login-action@v2 with: @@ -434,7 +437,7 @@ jobs: - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@v0.36.0 with: - image-ref: ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{ env.IMAGE_TAG }} + image-ref: ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{ env.RESOLVED_IMAGE_TAG }} format: table exit-code: '0' ignore-unfixed: false From ea3b5e80b915ac79cbdb49da695613ba09bee4a1 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 29 Apr 2026 16:42:34 -0700 Subject: [PATCH 03/21] Change format --- .github/workflows/deploy-pm4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 0798604..cd632c2 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -438,7 +438,7 @@ jobs: uses: aquasecurity/trivy-action@v0.36.0 with: image-ref: ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{ env.RESOLVED_IMAGE_TAG }} - format: table + format: json exit-code: '0' ignore-unfixed: false vuln-type: os,library From 976e2054fdcba3752bb14d5eefbb08dea51b2ffe Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 29 Apr 2026 16:42:47 -0700 Subject: [PATCH 04/21] Save artifact --- .github/workflows/deploy-pm4.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index cd632c2..85fa588 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -439,6 +439,7 @@ jobs: with: image-ref: ${{ secrets.REGISTRY_HOST }}/processmaker/enterprise:${{ env.RESOLVED_IMAGE_TAG }} format: json + output: trivy-results.json exit-code: '0' ignore-unfixed: false vuln-type: os,library @@ -446,3 +447,10 @@ jobs: severity: MEDIUM,HIGH,CRITICAL env: TRIVY_TIMEOUT: 30m + + - name: Upload Trivy results + uses: actions/upload-artifact@v4 + with: + name: trivy-results-${{ github.run_id }} + path: trivy-results.json + if-no-files-found: warn From 352ffa984a60d0ce6e3f2325120dfeb8d4e36536 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 6 May 2026 06:54:45 -0700 Subject: [PATCH 05/21] Add pr sync script --- .cursor/rules/processmaker-org-github.mdc | 32 ++++++ .github/actions/common/action.yml | 119 +++++++++++++++++++++- .github/workflows/deploy-pm4.yml | 53 ++++++++++ 3 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 .cursor/rules/processmaker-org-github.mdc diff --git a/.cursor/rules/processmaker-org-github.mdc b/.cursor/rules/processmaker-org-github.mdc new file mode 100644 index 0000000..82edbff --- /dev/null +++ b/.cursor/rules/processmaker-org-github.mdc @@ -0,0 +1,32 @@ +--- +description: ProcessMaker/.github org-wide reusable workflows — repo purpose and CI patterns +alwaysApply: true +--- + +# ProcessMaker `.github` (org-wide) + +This repository is [ProcessMaker/.github](https://github.com/ProcessMaker/.github): **shared GitHub Actions workflows, scripts, and composite actions** for the ProcessMaker GitHub org. Consumer repositories do not copy this logic; they **call** a reusable workflow via `uses: //.github/workflows/.yml@` and `secrets: inherit` (pin is often `develop` or `main`). The org may still point `uses:` at the core app repo or at this repo depending on workflow—**follow the actual `uses:` in caller repos** when tracing behavior. + +## Repo “shape” the AI must keep in mind + +- **ProcessMaker core** (e.g. main application repo) and **other repos** (enterprise add-ons, `package-*`, customer/custom packages) **all wire the same reusable workflow entrypoint**. Locally you are often editing the **shared** workflow that runs in **many different repository contexts**. +- When changing jobs or steps, assume the caller may be **core**, **enterprise**, or **custom/package** unless you have verified otherwise. + +## Critical pattern: gate behavior with `if:` + +**Every consumer repo is configured to run the shared workflow** (same pattern, different workflow `name`, sometimes different `@ref` — commonly `develop` or `main`; the org tries to keep those aligned to avoid mass updates). + +Therefore: + +- Anything that should **only** run for certain repos (core vs package vs enterprise-only, etc.) **must** be guarded with job-level or step-level **`if:`** (or equivalent conditions), not by hoping only the “right” repos call the workflow. +- Prefer explicit conditions on **`github.repository`**, **`github.event.pull_request.head.repo.name`**, **`github.event.repository.name`**, or env vars your workflow already sets (e.g. `CI_PROJECT` / naming conventions) rather than implicit assumptions. + +## Consumer example + +Package repos typically have a thin wrapper workflow whose only real differences are **display name** and **pin branch**; see e.g. [package-webentry `deploy-package.yml`](https://github.com/ProcessMaker/package-webentry/blob/develop/.github/workflows/deploy-package.yml) (`uses: .../deploy-pm4.yml@develop`, `secrets: inherit`). + +When adding or tightening `if:` conditions, **think through all caller repo types** so shared CI stays green across the org. + +PHP packages have a composer.json and javascript packages have a package.json. Some have both. + +Processmaker core is the main consumer of all these packages. Its located at https://github.com/ProcessMaker/processmaker \ No newline at end of file diff --git a/.github/actions/common/action.yml b/.github/actions/common/action.yml index 7955c97..cd4d0bc 100644 --- a/.github/actions/common/action.yml +++ b/.github/actions/common/action.yml @@ -3,14 +3,26 @@ description: 'Here to dry up the workflow' inputs: token: - description: 'GitHub token' + description: 'GitHub token for git HTTPS and API (clone k8s repo, or sync merge when enabled)' required: true - + run_k8s_setup: + description: 'When true, resolve release branch and clone pm4-k8s-distribution' + required: false + default: 'true' + run_sync_merge_base: + description: 'When true, merge PR base into head when behind; may run npm run prod for public-only conflicts and push' + required: false + default: 'false' + package_path: + description: 'Path under workspace to the package git checkout (used by sync merge only)' + required: false + default: '.' runs: using: "composite" steps: - name: Determine the base branch + if: ${{ inputs.run_k8s_setup == 'true' }} run: | default_branch=${{ github.event.repository.default_branch }} base_branch=${{ github.event.pull_request.base.ref }} @@ -32,6 +44,7 @@ runs: shell: bash - name: Clone K8S + if: ${{ inputs.run_k8s_setup == 'true' }} run: | k8s_branch=$RELEASE_BRANCH @@ -44,4 +57,104 @@ runs: echo "*** k8s Branch: $k8s_branch ***" git clone --depth 1 -b "$k8s_branch" "https://${{ inputs.token }}@github.com/ProcessMaker/pm4-k8s-distribution.git" pm4-k8s-distribution echo "versionHelm=$(grep "version:" "pm4-k8s-distribution/charts/enterprise/Chart.yaml" | awk '{print $2}' | sed 's/\"//g')" >> $GITHUB_ENV - shell: bash \ No newline at end of file + shell: bash + + - name: Sync PR branch with base (merge when behind) + if: ${{ inputs.run_sync_merge_base == 'true' }} + env: + PACKAGE_PATH: ${{ inputs.package_path }} + BASE_REF: ${{ github.event.pull_request.base.ref }} + HEAD_REF: ${{ github.event.pull_request.head.ref }} + run: | + set -euo pipefail + pkg="${PACKAGE_PATH:-.}" + cd "$pkg" + + if ! git rev-parse --git-dir >/dev/null 2>&1; then + echo "::error::Not a git repository at $pkg" + exit 1 + fi + + git_name="${GH_USER:-github-actions[bot]}" + git_email="${GH_EMAIL:-41898282+github-actions[bot]@users.noreply.github.com}" + git config user.name "$git_name" + git config user.email "$git_email" + + echo "Fetching origin/${BASE_REF}..." + git fetch origin "$BASE_REF" + + if git merge-base --is-ancestor "origin/${BASE_REF}" HEAD; then + echo "PR head already contains origin/${BASE_REF}; nothing to merge." + exit 0 + fi + + echo "PR head is missing commits from origin/${BASE_REF}; merging..." + set +e + git merge "origin/${BASE_REF}" --no-edit + merge_status=$? + set -e + + if [[ "$merge_status" -eq 0 ]]; then + echo "Merge completed without conflicts; pushing." + git push origin "HEAD:refs/heads/${HEAD_REF}" + exit 0 + fi + + echo "Merge reported conflicts." + conflicted=() + while IFS= read -r line; do + [[ -n "$line" ]] && conflicted+=("$line") + done < <(git diff --name-only --diff-filter=U || true) + + if [[ ${#conflicted[@]} -eq 0 ]]; then + echo "No unmerged paths listed; aborting merge." + git merge --abort || true + exit 0 + fi + + only_public=true + for f in "${conflicted[@]}"; do + case "$f" in + public|public/*) ;; + *) only_public=false; break ;; + esac + done + + if [[ "$only_public" != true ]]; then + echo "Conflicts exist outside public/; aborting merge and exiting without failure." + git merge --abort || true + exit 0 + fi + + has_prod=false + if [[ -f package.json ]] && node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then + has_prod=true + fi + + if [[ "$has_prod" != true ]]; then + echo "No npm run prod available; cannot auto-resolve public conflicts." + git merge --abort || true + exit 0 + fi + + set +e + npm run prod + prod_status=$? + set -e + if [[ "$prod_status" -ne 0 ]]; then + echo "npm run prod failed during conflict resolution; aborting merge." + git merge --abort || true + exit 0 + fi + + if git diff --name-only --diff-filter=U | grep -q .; then + echo "Conflicts remain after npm run prod; aborting merge." + git merge --abort || true + exit 0 + fi + + git add -A + git commit --no-edit || git commit -m "Merge origin/${BASE_REF} and rebuild public assets" + git push origin "HEAD:refs/heads/${HEAD_REF}" + echo "Pushed merge and rebuilt public assets." + shell: bash diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 85fa588..3c8e012 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -29,6 +29,8 @@ env: GH_EMAIL: ${{ secrets.GH_EMAIL }} DOM_EKS: ${{ secrets.DOM_EKS }} GIT_TOKEN: ${{ secrets.GIT_TOKEN }} + # Git fetch/push for npm + sync-base job: point at another secret (e.g. GITHUB_TOKEN) when migrating off GIT_TOKEN. + PM4_SYNC_GIT_TOKEN: ${{ secrets.GIT_TOKEN }} BUILD_BASE: ${{ (contains(github.event.pull_request.body, 'ci:build-base') || github.event_name == 'schedule') && '1' || '0' }} MULTITENANCY: ${{ (contains(github.event.pull_request.body, 'ci:multitenancy')) && 'true' || 'false' }} BASE_IMAGE: ${{ secrets.REGISTRY_HOST }}/processmaker/processmaker:base @@ -41,6 +43,57 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}-${{ inputs.delete }} cancel-in-progress: true jobs: + npmInstallAndSyncBase: + name: npm install and sync PR with base + if: github.event_name == 'pull_request' && github.event.action != 'closed' && inputs.delete == '' + runs-on: ${{ vars.RUNNER }} + defaults: + run: + working-directory: repo + steps: + - name: Checkout package + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + path: repo + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + token: ${{ env.PM4_SYNC_GIT_TOKEN }} + persist-credentials: true + + - name: Checkout shared workflows (composite action) + uses: actions/checkout@v4 + with: + repository: processmaker/.github + path: _pm4_github + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: npm install (when package.json exists) + run: | + set -euo pipefail + if [[ ! -f package.json ]]; then + echo "No package.json; skipping npm steps." + exit 0 + fi + npm install + if node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then + npm run prod + else + echo "No prod script in package.json; skipping npm run prod." + fi + + - name: Merge base when behind (optional public/ auto-resolve) + uses: ./_pm4_github/.github/actions/common + with: + token: ${{ env.PM4_SYNC_GIT_TOKEN }} + run_k8s_setup: 'false' + run_sync_merge_base: 'true' + package_path: repo + imageEKS: name: build-docker-image-EKS if: github.event.action != 'closed' && inputs.delete == '' From 9232c708e213838aba7a9e6b089b5f2df52605ac Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 6 May 2026 09:37:26 -0700 Subject: [PATCH 06/21] Fix --- .github/workflows/deploy-pm4.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 3c8e012..19ca918 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -66,6 +66,7 @@ jobs: with: repository: processmaker/.github path: _pm4_github + ref: ${{ github.workflow_sha }} - name: Set up Node uses: actions/setup-node@v4 From 01fb3aea66019abb3b23faaeeb32af4eb62a09fa Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 6 May 2026 11:07:56 -0700 Subject: [PATCH 07/21] Fix --- .github/workflows/deploy-pm4.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 19ca918..bc121e7 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -64,9 +64,9 @@ jobs: - name: Checkout shared workflows (composite action) uses: actions/checkout@v4 with: - repository: processmaker/.github + repository: ${{ job.workflow_repository }} + ref: ${{ job.workflow_sha }} path: _pm4_github - ref: ${{ github.workflow_sha }} - name: Set up Node uses: actions/setup-node@v4 From e11d18a30074e90faf20c2d4ec34ae1351a8f667 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 6 May 2026 15:16:59 -0700 Subject: [PATCH 08/21] Fix --- .github/workflows/deploy-pm4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index bc121e7..b140fc8 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -82,7 +82,7 @@ jobs: fi npm install if node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then - npm run prod + NODE_OPTIONS=--max-old-space-size=8000 npm run prod else echo "No prod script in package.json; skipping npm run prod." fi From aa0ebd509f9bb7a5f9e9696fc9bcb2d4ff6da419 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 12:32:41 -0700 Subject: [PATCH 09/21] Update --- .github/workflows/deploy-pm4.yml | 1 + .gitignore | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 .gitignore diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index b140fc8..edd7de6 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -67,6 +67,7 @@ jobs: repository: ${{ job.workflow_repository }} ref: ${{ job.workflow_sha }} path: _pm4_github + token: ${{ env.PM4_SYNC_GIT_TOKEN }} - name: Set up Node uses: actions/setup-node@v4 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..12e0b65 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.envrc +docker From b225478211a5aa7f1d439e576242b5935bd9ab52 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 12:58:26 -0700 Subject: [PATCH 10/21] Update --- .github/workflows/deploy-pm4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index edd7de6..f72c2b3 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -83,7 +83,7 @@ jobs: fi npm install if node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then - NODE_OPTIONS=--max-old-space-size=8000 npm run prod + npm run prod else echo "No prod script in package.json; skipping npm run prod." fi From bae71bfb8a633011e723c6df1a0529e12d31a250 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 13:00:53 -0700 Subject: [PATCH 11/21] Update --- .github/workflows/deploy-pm4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index f72c2b3..2234bfb 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -475,7 +475,7 @@ jobs: trivyScan: name: Trivy vulnerability scan - # if: github.event.action != 'closed' && inputs.delete == '' && !contains(github.event.pull_request.body, 'ci:skip-build') + if: github.event.action != 'closed' && inputs.delete == '' needs: imageEKS runs-on: ${{ vars.RUNNER }} steps: From e6873a8146e6a5c20d5fba441dcf20b56ba3c366 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 15:13:31 -0700 Subject: [PATCH 12/21] Update --- .../actions/common/Dockerfile.npm-run-prod | 61 +++++++++++++++++++ .github/workflows/deploy-pm4.yml | 47 ++++++++++---- 2 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 .github/actions/common/Dockerfile.npm-run-prod diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod new file mode 100644 index 0000000..5b6aacd --- /dev/null +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -0,0 +1,61 @@ +# npm install + `npm run prod` in a container (avoids Mix/webpack stalling with no output on some runners). +# +# Local stand-in for ProcessMaker core (clone develop): build from this repo root — context can be anything; +# docker build -f .github/actions/common/Dockerfile.npm-run-prod . +# Another branch: +# docker build -f .github/actions/common/Dockerfile.npm-run-prod --build-arg PM4_BRANCH=my-branch . +# +# GitHub Actions (package / PR checkout): context is the package repo; use target `npm-run-prod-context`: +# docker build --target npm-run-prod-context -f path/to/Dockerfile.npm-run-prod . +# +# If `npm run prod` dies with exit 137 (Killed): increase Docker memory or pass: +# --build-arg NODE_MAX_OLD_SPACE_SIZE=4096 + +FROM ubuntu:24.04 AS base + +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + gnupg \ + git \ + python3 \ + make \ + g++ \ + bzip2 \ + && rm -rf /var/lib/apt/lists/* + +RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ + && apt-get install -y --no-install-recommends nodejs \ + && rm -rf /var/lib/apt/lists/* + +# --- PR package checkout (deploy-pm4.yml `npmInstallAndSyncBase`) --- +FROM base AS sources-context +WORKDIR /repo +COPY . . + +FROM sources-context AS npm-run-prod-context +ARG NODE_MAX_OLD_SPACE_SIZE +RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ + && npm install +RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ + && if node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then \ + npm run prod; \ + else \ + echo "No prod script in package.json; skipping npm run prod."; \ + fi + +# --- Clone ProcessMaker core (local / scanners) — default `docker build` target --- +FROM base AS sources-clone +ARG PM4_BRANCH=develop +ARG PM4_REPO=https://github.com/ProcessMaker/processmaker.git +WORKDIR /repo +RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . + +FROM sources-clone AS npm-run-prod +ARG NODE_MAX_OLD_SPACE_SIZE +RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ + && npm install +RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ + && npm run prod diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 2234bfb..c0177b4 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -69,24 +69,47 @@ jobs: path: _pm4_github token: ${{ env.PM4_SYNC_GIT_TOKEN }} - - name: Set up Node - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: npm install (when package.json exists) + - name: Runner and Docker diagnostics + working-directory: ${{ github.workspace }} + run: | + set -euo pipefail + echo '::group::Runner identity' + echo "RUNNER_NAME=${RUNNER_NAME:-}" + echo "RUNNER_OS=${RUNNER_OS:-}" + echo "RUNNER_ARCH=${RUNNER_ARCH:-}" + echo "RUNNER_ENVIRONMENT=${RUNNER_ENVIRONMENT:-}" + echo "GITHUB_REPOSITORY=${GITHUB_REPOSITORY}" + uname -a || true + echo '::endgroup::' + echo '::group::CPU / memory / disk' + if command -v nproc >/dev/null 2>&1; then echo "nproc=$(nproc)"; fi + if command -v sysctl >/dev/null 2>&1; then echo "hw.ncpu=$(sysctl -n hw.ncpu 2>/dev/null || true)"; fi + if command -v free >/dev/null 2>&1; then free -h; else echo "(free not available; non-Linux runner?)"; fi + df -h "${GITHUB_WORKSPACE}" 2>/dev/null || df -h . || true + echo '::endgroup::' + echo '::group::Docker' + docker version + docker info 2>/dev/null | head -n 120 || true + echo '::endgroup::' + + - name: npm install + prod (Docker) + env: + DOCKER_BUILDKIT: 1 + BUILDKIT_PROGRESS: plain run: | set -euo pipefail if [[ ! -f package.json ]]; then echo "No package.json; skipping npm steps." exit 0 fi - npm install - if node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then - npm run prod - else - echo "No prod script in package.json; skipping npm run prod." - fi + echo "=== Build start $(date -uIs) (UTC) ===" + if command -v free >/dev/null 2>&1; then free -h || true; fi + docker build \ + --progress=plain \ + --target npm-run-prod-context \ + -f "${GITHUB_WORKSPACE}/_pm4_github/.github/actions/common/Dockerfile.npm-run-prod" \ + . + echo "=== Build end $(date -uIs) (UTC) ===" - name: Merge base when behind (optional public/ auto-resolve) uses: ./_pm4_github/.github/actions/common From df0e62bb2cbe3bb8981192766e10456521ee6f13 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 15:39:42 -0700 Subject: [PATCH 13/21] Update --- .../actions/common/Dockerfile.npm-run-prod | 62 ++----------------- .github/workflows/deploy-pm4.yml | 54 +--------------- 2 files changed, 8 insertions(+), 108 deletions(-) diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod index 5b6aacd..c1f0675 100644 --- a/.github/actions/common/Dockerfile.npm-run-prod +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -1,61 +1,9 @@ -# npm install + `npm run prod` in a container (avoids Mix/webpack stalling with no output on some runners). -# -# Local stand-in for ProcessMaker core (clone develop): build from this repo root — context can be anything; -# docker build -f .github/actions/common/Dockerfile.npm-run-prod . -# Another branch: -# docker build -f .github/actions/common/Dockerfile.npm-run-prod --build-arg PM4_BRANCH=my-branch . -# -# GitHub Actions (package / PR checkout): context is the package repo; use target `npm-run-prod-context`: -# docker build --target npm-run-prod-context -f path/to/Dockerfile.npm-run-prod . -# -# If `npm run prod` dies with exit 137 (Killed): increase Docker memory or pass: -# --build-arg NODE_MAX_OLD_SPACE_SIZE=4096 - -FROM ubuntu:24.04 AS base - -ENV DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ - curl \ - gnupg \ - git \ - python3 \ - make \ - g++ \ - bzip2 \ - && rm -rf /var/lib/apt/lists/* - -RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ - && apt-get install -y --no-install-recommends nodejs \ - && rm -rf /var/lib/apt/lists/* - -# --- PR package checkout (deploy-pm4.yml `npmInstallAndSyncBase`) --- -FROM base AS sources-context -WORKDIR /repo -COPY . . - -FROM sources-context AS npm-run-prod-context -ARG NODE_MAX_OLD_SPACE_SIZE -RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ - && npm install -RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ - && if node -e "const p=require('./package.json'); process.exit(p.scripts&&p.scripts.prod?0:1)"; then \ - npm run prod; \ - else \ - echo "No prod script in package.json; skipping npm run prod."; \ - fi - -# --- Clone ProcessMaker core (local / scanners) — default `docker build` target --- -FROM base AS sources-clone +FROM node:24-alpine ARG PM4_BRANCH=develop ARG PM4_REPO=https://github.com/ProcessMaker/processmaker.git WORKDIR /repo -RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . -FROM sources-clone AS npm-run-prod -ARG NODE_MAX_OLD_SPACE_SIZE -RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ - && npm install -RUN if [ -n "${NODE_MAX_OLD_SPACE_SIZE}" ]; then export NODE_OPTIONS="--max-old-space-size=${NODE_MAX_OLD_SPACE_SIZE}"; fi \ - && npm run prod +RUN apk add git +RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . +RUN npm install +RUN npm run prod \ No newline at end of file diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index c0177b4..2daba7c 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -49,18 +49,8 @@ jobs: runs-on: ${{ vars.RUNNER }} defaults: run: - working-directory: repo + working-directory: npm-run-prod steps: - - name: Checkout package - uses: actions/checkout@v4 - with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - path: repo - fetch-depth: 0 - ref: ${{ github.event.pull_request.head.sha }} - token: ${{ env.PM4_SYNC_GIT_TOKEN }} - persist-credentials: true - - name: Checkout shared workflows (composite action) uses: actions/checkout@v4 with: @@ -69,55 +59,17 @@ jobs: path: _pm4_github token: ${{ env.PM4_SYNC_GIT_TOKEN }} - - name: Runner and Docker diagnostics - working-directory: ${{ github.workspace }} - run: | - set -euo pipefail - echo '::group::Runner identity' - echo "RUNNER_NAME=${RUNNER_NAME:-}" - echo "RUNNER_OS=${RUNNER_OS:-}" - echo "RUNNER_ARCH=${RUNNER_ARCH:-}" - echo "RUNNER_ENVIRONMENT=${RUNNER_ENVIRONMENT:-}" - echo "GITHUB_REPOSITORY=${GITHUB_REPOSITORY}" - uname -a || true - echo '::endgroup::' - echo '::group::CPU / memory / disk' - if command -v nproc >/dev/null 2>&1; then echo "nproc=$(nproc)"; fi - if command -v sysctl >/dev/null 2>&1; then echo "hw.ncpu=$(sysctl -n hw.ncpu 2>/dev/null || true)"; fi - if command -v free >/dev/null 2>&1; then free -h; else echo "(free not available; non-Linux runner?)"; fi - df -h "${GITHUB_WORKSPACE}" 2>/dev/null || df -h . || true - echo '::endgroup::' - echo '::group::Docker' - docker version - docker info 2>/dev/null | head -n 120 || true - echo '::endgroup::' - - name: npm install + prod (Docker) env: DOCKER_BUILDKIT: 1 BUILDKIT_PROGRESS: plain run: | - set -euo pipefail if [[ ! -f package.json ]]; then echo "No package.json; skipping npm steps." exit 0 fi - echo "=== Build start $(date -uIs) (UTC) ===" - if command -v free >/dev/null 2>&1; then free -h || true; fi - docker build \ - --progress=plain \ - --target npm-run-prod-context \ - -f "${GITHUB_WORKSPACE}/_pm4_github/.github/actions/common/Dockerfile.npm-run-prod" \ - . - echo "=== Build end $(date -uIs) (UTC) ===" - - - name: Merge base when behind (optional public/ auto-resolve) - uses: ./_pm4_github/.github/actions/common - with: - token: ${{ env.PM4_SYNC_GIT_TOKEN }} - run_k8s_setup: 'false' - run_sync_merge_base: 'true' - package_path: repo + + docker build -f ./_pm4_github/.github/actions/common/Dockerfile.npm-run-prod --build-arg PM4_BRANCH=${{ env.CI_PACKAGE_BRANCH }} . imageEKS: name: build-docker-image-EKS From 60723f95d73264420c3e2d28cbf177d5435aad74 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 17:06:10 -0700 Subject: [PATCH 14/21] Update --- .github/actions/common/Dockerfile.npm-run-prod | 2 +- .github/workflows/deploy-pm4.yml | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod index c1f0675..9c633d8 100644 --- a/.github/actions/common/Dockerfile.npm-run-prod +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -6,4 +6,4 @@ WORKDIR /repo RUN apk add git RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . RUN npm install -RUN npm run prod \ No newline at end of file +RUN NODE_OPTIONS="--max-old-space-size-percentage=75" npm run prod \ No newline at end of file diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 2daba7c..299a020 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -69,7 +69,12 @@ jobs: exit 0 fi - docker build -f ./_pm4_github/.github/actions/common/Dockerfile.npm-run-prod --build-arg PM4_BRANCH=${{ env.CI_PACKAGE_BRANCH }} . + docker build \ + --memory=8g \ + --cpu-shares=512 \ + --build-arg PM4_BRANCH=${{ env.CI_PACKAGE_BRANCH }} \ + -f ./_pm4_github/.github/actions/common/Dockerfile.npm-run-prod \ + . imageEKS: name: build-docker-image-EKS From 55eba0875842a1f9da8981197124b55e18f60c60 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 17:13:26 -0700 Subject: [PATCH 15/21] Update --- .github/workflows/deploy-pm4.yml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 299a020..c1863dc 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -49,8 +49,18 @@ jobs: runs-on: ${{ vars.RUNNER }} defaults: run: - working-directory: npm-run-prod + working-directory: repo steps: + - name: Checkout package + uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name }} + path: repo + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + token: ${{ env.PM4_SYNC_GIT_TOKEN }} + persist-credentials: true + - name: Checkout shared workflows (composite action) uses: actions/checkout@v4 with: @@ -76,6 +86,14 @@ jobs: -f ./_pm4_github/.github/actions/common/Dockerfile.npm-run-prod \ . + - name: Merge base when behind (optional public/ auto-resolve) + uses: ./_pm4_github/.github/actions/common + with: + token: ${{ env.PM4_SYNC_GIT_TOKEN }} + run_k8s_setup: 'false' + run_sync_merge_base: 'true' + package_path: repo + imageEKS: name: build-docker-image-EKS if: github.event.action != 'closed' && inputs.delete == '' From 0a87d7267e6f7607c5af586d75c1d866dcb46f23 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Tue, 12 May 2026 17:21:15 -0700 Subject: [PATCH 16/21] Update --- .github/workflows/deploy-pm4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index c1863dc..487aa2c 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -83,7 +83,7 @@ jobs: --memory=8g \ --cpu-shares=512 \ --build-arg PM4_BRANCH=${{ env.CI_PACKAGE_BRANCH }} \ - -f ./_pm4_github/.github/actions/common/Dockerfile.npm-run-prod \ + -f "${GITHUB_WORKSPACE}/_pm4_github/.github/actions/common/Dockerfile.npm-run-prod" \ . - name: Merge base when behind (optional public/ auto-resolve) From a653e7ddf601a3e27ee586529d46f97181ecd693 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 13 May 2026 11:16:57 -0700 Subject: [PATCH 17/21] Update --- .github/actions/common/Dockerfile.npm-run-prod | 2 +- .github/workflows/deploy-pm4.yml | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod index 9c633d8..53f1f95 100644 --- a/.github/actions/common/Dockerfile.npm-run-prod +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -6,4 +6,4 @@ WORKDIR /repo RUN apk add git RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . RUN npm install -RUN NODE_OPTIONS="--max-old-space-size-percentage=75" npm run prod \ No newline at end of file +RUN NODE_OPTIONS="--max-old-space-size=8000" npm run prod \ No newline at end of file diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index 487aa2c..cd35bea 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -78,8 +78,12 @@ jobs: echo "No package.json; skipping npm steps." exit 0 fi - - docker build \ + set -euxo pipefail + docker version + docker info + free -h + df -h + docker build --progress=plain \ --memory=8g \ --cpu-shares=512 \ --build-arg PM4_BRANCH=${{ env.CI_PACKAGE_BRANCH }} \ From 636e4ba9578d93ffdd340c017b26ed91e60c5c41 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 13 May 2026 11:40:48 -0700 Subject: [PATCH 18/21] Update --- .github/workflows/deploy-pm4.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-pm4.yml b/.github/workflows/deploy-pm4.yml index cd35bea..3d6d129 100644 --- a/.github/workflows/deploy-pm4.yml +++ b/.github/workflows/deploy-pm4.yml @@ -84,7 +84,7 @@ jobs: free -h df -h docker build --progress=plain \ - --memory=8g \ + --memory=12g \ --cpu-shares=512 \ --build-arg PM4_BRANCH=${{ env.CI_PACKAGE_BRANCH }} \ -f "${GITHUB_WORKSPACE}/_pm4_github/.github/actions/common/Dockerfile.npm-run-prod" \ From d1769c77d8beca17ce8e0871b1b8ba5cab9be435 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Wed, 13 May 2026 19:53:35 -0700 Subject: [PATCH 19/21] Update --- .github/actions/common/Dockerfile.npm-run-prod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod index 53f1f95..b9af1ee 100644 --- a/.github/actions/common/Dockerfile.npm-run-prod +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -6,4 +6,4 @@ WORKDIR /repo RUN apk add git RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . RUN npm install -RUN NODE_OPTIONS="--max-old-space-size=8000" npm run prod \ No newline at end of file +RUN NODE_OPTIONS="--max-old-space-size=4000" npm run prod \ No newline at end of file From d583f6acbaf189a0f172527bb7db005faa950192 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Thu, 14 May 2026 09:21:27 -0700 Subject: [PATCH 20/21] Update --- .github/actions/common/Dockerfile.npm-run-prod | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod index b9af1ee..873da3a 100644 --- a/.github/actions/common/Dockerfile.npm-run-prod +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -1,9 +1,11 @@ FROM node:24-alpine ARG PM4_BRANCH=develop ARG PM4_REPO=https://github.com/ProcessMaker/processmaker.git +RUN apk add git + WORKDIR /repo -RUN apk add git RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . +RUN npx update-browserslist-db@latest RUN npm install -RUN NODE_OPTIONS="--max-old-space-size=4000" npm run prod \ No newline at end of file +RUN NODE_OPTIONS="--max-old-space-size=6000" npm run prod --verbose \ No newline at end of file From 9264945d7d2052d7f097ff5e1f5dd2d09ae0de95 Mon Sep 17 00:00:00 2001 From: Nolan Ehrstrom Date: Thu, 14 May 2026 09:38:52 -0700 Subject: [PATCH 21/21] Update --- .github/actions/common/Dockerfile.npm-run-prod | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/actions/common/Dockerfile.npm-run-prod b/.github/actions/common/Dockerfile.npm-run-prod index 873da3a..4e30b0a 100644 --- a/.github/actions/common/Dockerfile.npm-run-prod +++ b/.github/actions/common/Dockerfile.npm-run-prod @@ -8,4 +8,14 @@ WORKDIR /repo RUN git clone --depth 1 --branch "${PM4_BRANCH}" --single-branch "${PM4_REPO}" . RUN npx update-browserslist-db@latest RUN npm install -RUN NODE_OPTIONS="--max-old-space-size=6000" npm run prod --verbose \ No newline at end of file +# RUN NODE_OPTIONS="--max-old-space-size=6000" npm run prod --verbose + +RUN NODE_OPTIONS="--max-old-space-size=6000" npm run prod --verbose & \ + BUILD_PID=$!; \ + sleep 30; \ + echo "=== Memory after 30s ===" && free -h && ps aux | grep -i node; \ + sleep 60; \ + echo "=== Memory after 90s ===" && free -h && ps aux | grep -i node; \ + sleep 120; \ + echo "=== Memory after 210s ===" && free -h && ps aux | grep -i node; \ + wait $BUILD_PID \ No newline at end of file