Composite action for Magento package validate and release to Forgejo Composer registry.
Find a file
2026-06-10 14:17:05 -06:00
references FEATURE: Unify Cocobolo + Kalicr package CI in polished action 2026-06-10 14:03:58 -06:00
scripts 🐛 BUGFIX #1654: Stabilize package action workflow env 2026-06-10 14:17:05 -06:00
templates 🐛 BUGFIX #1654: Stabilize package action workflow env 2026-06-10 14:17:05 -06:00
action.yml FEATURE: Composite action for Magento package validate and release 2026-06-10 10:58:57 -06:00
README.md 🐛 BUGFIX #1654: Stabilize package action workflow env 2026-06-10 14:17:05 -06:00

actions-magento-package

Composite action to validate and publish Magento 2 Composer modules (magento2-module) to the Forgejo Package Registry.

Consolidates learnings from Cocobolo (mature inline pipelines) and Kalicr (kalicr-core legacy, kalicr-zunify first adopter) into one reusable action for both orgs (registry_org: kalicr | cocobolo).

Why this exists

Before: each package repo duplicated ~300 lines of package.yml (six parallel validate jobs + release-readiness + release). After: consumers keep ~100 lines of YAML with package metadata only; all logic lives here.

Same operational model as actions-magento-deploy: pin by commit SHA, never float on a branch.

Job graph

                    ┌─────────────┐
  PR/push develop   │  validate   │  php/xml/contract/strict/security/archive
  feature/*         └──────┬──────┘
                           │
  PR → production          ▼
                    ┌──────────────────┐
                    │ release-readiness │  semver bump, no duplicate tags
                    └────────┬─────────┘
                             │
  push production            ▼
                    ┌─────────────┐
                    │   release   │  tag + Forgejo release + registry ZIP
                    └─────────────┘

release needs [validate, release-readiness] — a failing validate cannot publish.

Modes

INPUT_MODE When
validate Every non-tag push and PR
release-readiness PR to production, or production push/dispatch
release production push or workflow_dispatch

Validate gates

Single job, same coverage as Cocobolo's six parallel jobs:

  • php -l on all .php
  • XML validation (xmllint or PHP SimpleXML fallback)
  • composer validate --no-check-lock --no-check-publish
  • Module contract: name, type, PSR-4, registration.php, module.xml
  • composer.json versionmodule.xml setup_version
  • declare(strict_types=1) on every PHP file
  • Dangerous functions scan with \bexec\( (no curl_exec false positives)
  • Required files: README.md, CHANGELOG.md, registration.php, composer.json, etc/module.xml
  • Blocks committed .env, auth.json, credentials.json
  • Archive smoke test (ZIP build + unzip -t)

Release behavior

On push to production:

  1. Create tag v{version} via Forgejo API
  2. Create Forgejo release
  3. Build ZIP (excludes .git, .forgejo, .actions)
  4. Publish to https://git.kalicr.com/api/packages/{registry_org}/composer

Version from composer.json, or workflow_dispatch input override.

Event Tag/release Registry 409
pushproduction Created; 409 = fail 409 = fail
workflow_dispatch Skipped 409 = warning (idempotent retry)

Consumer workflow (Forgejo)

kalicr/actions-magento-package must stay public. Forgejo cannot reliably consume private reusable action repos across repositories; private action repos fail during checkout with remote: User permission denied / HTTP 403.

Working pattern (proven on kalicr-zunify):

  1. Checkout package repo
  2. Checkout kalicr/actions-magento-package.actions/magento-package (ref: PACKAGE_ACTION_REF)
  3. Run bash "${FORGEJO_ACTION_PATH}/scripts/run-package.sh" with explicit per-step INPUT_* env vars

Keep FORGEJO_ACTION_PATH and package metadata on the execution step itself. This Forgejo/act runner does not reliably expose workflow-level env values to run commands; relying on global env can produce bash: /scripts/run-package.sh: No such file or directory.

Copy templates/package.workflow.yml and replace PACKAGE_* placeholders. See references/MIGRATION.md for full migration steps.

Inputs

Metadata (all modes)

Input Example
INPUT_PACKAGE_NAME kalicr/zunify
INPUT_MAGENTO_MODULE Kalicr_Zunify
INPUT_PSR4_NAMESPACE Kalicr\Zunify\
INPUT_REGISTRY_ORG kalicr or cocobolo
INPUT_ARCHIVE_BASENAME kalicr-zunify
INPUT_FORGEJO_OWNER kalicr
INPUT_FORGEJO_REPO kalicr-zunify

Release only

Input Source
INPUT_PACKAGE_USERNAME secret FORGEJO_PACKAGE_USERNAME
INPUT_PACKAGE_TOKEN secret FORGEJO_PACKAGE_TOKEN
INPUT_GITHUB_SHA ${{ github.sha }}
INPUT_GITHUB_REF_NAME ${{ github.ref_name }}
INPUT_GITHUB_EVENT_NAME ${{ github.event_name }}
INPUT_WORKFLOW_VERSION optional workflow_dispatch input

Structure

action.yml
scripts/
  run-package.sh      # mode dispatcher
  validate.sh
  release-readiness.sh
  release.sh
  lib.sh
templates/
  package.workflow.yml
references/
  MIGRATION.md

Bootstrap (first-time org setup)

Forgejo org repos cannot be created via git push --set-upstream. Create empty repo in UI:

  1. https://git.kalicr.com/org/kalicr/repos/newactions-magento-package, default branch production
  2. Push local production branch
  3. Pin PACKAGE_ACTION_REF in each consumer to the resulting commit SHA

Operational rules

  • Keep this action repository public so Forgejo consumers can checkout it across repos
  • Pin action by commit SHA in PACKAGE_ACTION_REF, not branch name
  • Keep critical FORGEJO_ACTION_PATH/INPUT_* values on each execution step, not only workflow-level env
  • Bump composer.json + module.xml before PR developproduction
  • Publish secrets live at org level (FORGEJO_PACKAGE_*); consumer auth.json tokens are for install only
  • Do not cut release tags manually except disaster recovery

Release flow (summary)

feature/* → PR develop → PR production → push production
  → validate + release-readiness + release
  → tag v{X.Y.Z} + Forgejo Packages

Install in Magento projects:

composer require kalicr/zunify:1.0.2
# or
composer require cocobolo/module-visual-search:0.2.0

Consumers (migration status)

Package Org Status
kalicr-zunify kalicr Adopted (reference)
cocobolo-visual-search cocobolo Inline → migrate
cocobolo-visual-search-ui cocobolo Inline → migrate
cocobolo-core cocobolo Inline → migrate (+ release-readiness)
kalicr-core kalicr Legacy tag publish → migrate