mirror of
https://github.com/graycoreio/github-actions-magento2.git
synced 2026-06-08 19:46:41 +00:00
Compare commits
151 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a097371e37 | |||
| 5ee0768610 | |||
| 3c51e99538 | |||
| 32a5fd2bad | |||
| 91bd008e62 | |||
| 36953b919c | |||
| 83f9433da0 | |||
| a7d48f567e | |||
| 76eb9064ff | |||
| 147245e120 | |||
| 4df4b25e05 | |||
| fa8e597365 | |||
| 1ea5a10ef6 | |||
| 863444afbd | |||
| befe0807f7 | |||
| 1e63c019ed | |||
| ebfdeb0b73 | |||
| 8a0f197a13 | |||
| 0bf08ef692 | |||
| 35c1ace2bc | |||
| d07afbacd0 | |||
| b71bb8b4aa | |||
| e39dd46f9c | |||
| b98313e100 | |||
| 0c7d14d885 | |||
| 6d4ca8d669 | |||
| b790da1859 | |||
| e89f6ad2e0 | |||
| 8e82fcc893 | |||
| 83ef32c838 | |||
| de7c47f07d | |||
| a2e3e7758b | |||
| e6bb7be524 | |||
| 3e9f95ee56 | |||
| 9c56da774b | |||
| 8c4fefd979 | |||
| d1a31d260d | |||
| d37f001ab6 | |||
| c5221f0d68 | |||
| 1fcb3618c0 | |||
| 4fc491bc1a | |||
| 5df6c1a0bd | |||
| ff5f76339b | |||
| 0df8ac6e57 | |||
| ef06f4566b | |||
| 4c9a28930b | |||
| 22627e1000 | |||
| b0131f0fa0 | |||
| 23c77e10c8 | |||
| 5fb823da94 | |||
| 38423ddb9b | |||
| d7959941c6 | |||
| 74f1e3ec39 | |||
| d38c375b83 | |||
| dcbd219ac1 | |||
| 761188e82f | |||
| aa1b545010 | |||
| 45d1df0162 | |||
| baef64bc0a | |||
| 59f87b6b2e | |||
| 0cbc4297b1 | |||
| c78e635688 | |||
| 5c04c25fe8 | |||
| 8d00f8149a | |||
| 2d7238de14 | |||
| 44e7c34892 | |||
| c53607cca8 | |||
| a729f8b2fd | |||
| f6a7355bd9 | |||
| 307f527997 | |||
| 85b7909eb1 | |||
| 837f1da96b | |||
| d311df7966 | |||
| a7e327d44f | |||
| c786530c3e | |||
| 483ec3ac17 | |||
| a1c6246c78 | |||
| 87989bb250 | |||
| bdb9528f8c | |||
| 6a520d49fd | |||
| 212f9a8e86 | |||
| 0808fab9c3 | |||
| bbd830745f | |||
| e31f6f656a | |||
| 198bc1072a | |||
| 3c0a90f92b | |||
| c115395583 | |||
| 20cbf5d06a | |||
| ff6279a518 | |||
| b74bdcde41 | |||
| 1c312fe567 | |||
| 62d2aec976 | |||
| 771dd05439 | |||
| f8036173e1 | |||
| bbecc7f5f9 | |||
| db1267a94b | |||
| 90babb16bf | |||
| 93c0b480e2 | |||
| 28f9e498aa | |||
| 4001e8118b | |||
| b90317db60 | |||
| ef5e69859c | |||
| 1f4db0036c | |||
| e1a8a81488 | |||
| 3fad3a8995 | |||
| f8eff3c183 | |||
| ac4d16919b | |||
| 5009cbf6da | |||
| 4a0dcce0c9 | |||
| 5989e53c34 | |||
| 7a3a4fdb6d | |||
| d4f4f9f468 | |||
| 702ab13a0a | |||
| 070b7b9901 | |||
| 7e828eef67 | |||
| dd543ffdea | |||
| a2a45eb2fe | |||
| fa5620fc05 | |||
| d80befbe9b | |||
| d5c744e155 | |||
| 953de845eb | |||
| de415eaff5 | |||
| 8f3c6eb927 | |||
| 98923b24c5 | |||
| a92fe04503 | |||
| b510ea21e3 | |||
| 7799f0f9bf | |||
| 2ef157ef8a | |||
| 7e40a62efa | |||
| b4526dbb52 | |||
| e6be791eed | |||
| 2855f468ef | |||
| 7e70ee93ef | |||
| d29e574475 | |||
| c19912dc4b | |||
| c26e84f693 | |||
| 48902e8e6a | |||
| 07f89530df | |||
| 505179ce7b | |||
| 34ddee6aef | |||
| 462e60345e | |||
| f45372b796 | |||
| 7b5ccf7d9d | |||
| dc2f775d75 | |||
| 5f3ba73bc6 | |||
| 86b01b17fa | |||
| c2c3755729 | |||
| 5d47cda771 | |||
| dc750a9f2f | |||
| 7c0bc65842 | |||
| 89912779a9 |
@@ -0,0 +1,13 @@
|
||||
---
|
||||
name: grill-me
|
||||
description: Interview the user relentlessly about a plan or design until reaching shared understanding, resolving each branch of the decision tree. Use when user wants to stress-test a plan, get grilled on their design, or mentions "grill me".
|
||||
---
|
||||
|
||||
Interview me relentlessly about every aspect of this plan until
|
||||
we reach a shared understanding. Walk down each branch of the design
|
||||
tree resolving dependencies between decisions one by one.
|
||||
|
||||
If a question can be answered by exploring the codebase, explore
|
||||
the codebase instead.
|
||||
|
||||
For each question, provide your recommended answer.
|
||||
@@ -0,0 +1,112 @@
|
||||
---
|
||||
name: new-versions
|
||||
description: Check magento/magento2 for newly published tags and add any missing entries to supported-version/src/versions/magento-open-source/{individual,composite}.json using Adobe's system requirements docs. Use when user wants to refresh Magento Open Source version data, mentions "new versions", or asks to check for new Magento releases.
|
||||
---
|
||||
|
||||
Refresh the Magento Open Source version data in this repo by adding any tags that have shipped recently but are not yet recorded.
|
||||
|
||||
## 1. Find new tags
|
||||
|
||||
List tags from `magento/magento2` via the GitHub API:
|
||||
|
||||
```
|
||||
gh api -X GET repos/magento/magento2/tags --paginate -q '.[].name' | head -50
|
||||
```
|
||||
|
||||
Focus on tags from the last several weeks. Tags look like `2.4.8-p4`, `2.4.7-p9`, etc. Ignore preview/RC tags unless the user asks otherwise.
|
||||
|
||||
For each candidate tag, get its publish date (needed for the `release` field):
|
||||
|
||||
```
|
||||
gh api repos/magento/magento2/git/refs/tags/<tag> -q '.object.url' | xargs -I{} gh api {} -q '.tagger.date // .author.date'
|
||||
```
|
||||
|
||||
## 2. Diff against the JSON files
|
||||
|
||||
The two files to check:
|
||||
|
||||
- `supported-version/src/versions/magento-open-source/individual.json` — one entry per concrete tag, keyed `magento/project-community-edition:<tag>`
|
||||
- `supported-version/src/versions/magento-open-source/composite.json` — range entries keyed `magento/project-community-edition:>=X.Y.Z <X.Y.(Z+1)`, plus the rolling entries `magento/project-community-edition` and `magento/project-community-edition:next`
|
||||
|
||||
A tag is "missing" if the `magento/project-community-edition:<tag>` key is absent from `individual.json`.
|
||||
|
||||
## 3. Fetch system requirements
|
||||
|
||||
For the minor version that the missing tag belongs to (e.g. `2.4.8` for `2.4.8-p4`), pull Adobe's system requirements page:
|
||||
|
||||
- https://experienceleague.adobe.com/en/docs/commerce-operations/installation-guide/system-requirements
|
||||
|
||||
Use `WebFetch` and extract: PHP, Composer, MySQL/MariaDB, Elasticsearch/OpenSearch, RabbitMQ, Redis/Valkey, Varnish, Nginx, supported OS. If a component (e.g. `elasticsearch`) is no longer listed for that minor version, omit the field from the new entry — do not carry it over from the previous patch. Compare the new entry against the most recent prior patch in `individual.json` to sanity-check which fields should be present.
|
||||
|
||||
For each service field, pin the **latest currently-published tag within the line Adobe lists**, derived from Docker Hub — not whatever the prior patch happened to carry.
|
||||
|
||||
- Adobe lists a major+minor (e.g. "Elasticsearch 8.19"): use the highest published `8.19.x` tag.
|
||||
- Adobe lists only a major (e.g. "Elasticsearch 8"): use the highest published `8.y.z` across all `8.x` minors (today: `8.19.15`).
|
||||
- Adobe lists multiple majors/lines (e.g. "OpenSearch 2.19, 3"): pick the newest line (`3`).
|
||||
|
||||
Query Docker Hub for the latest patch:
|
||||
|
||||
```
|
||||
curl -s "https://hub.docker.com/v2/repositories/library/elasticsearch/tags?page_size=100&name=8.19" \
|
||||
| python3 -c "import json,sys; d=json.load(sys.stdin); tags=[t['name'] for t in d['results'] if t['name'].startswith('8.19.') and t['name'].split('.')[2].isdigit()]; print(max(tags, key=lambda t:[int(x) for x in t.split('.')]))"
|
||||
```
|
||||
|
||||
For OpenSearch swap `library/elasticsearch` → `opensearchproject/opensearch`. Services already using rolling minor tags (`redis:7.2`, `varnish:7.7`, `nginx:1.28`, `rabbitmq:4.1-management`) are already "latest of the line" and need no bump.
|
||||
|
||||
Also fetch Adobe's lifecycle policy page for the line's EOL date:
|
||||
|
||||
- https://experienceleague.adobe.com/en/docs/commerce-operations/release/planning/lifecycle-policy
|
||||
|
||||
## 4. Write the entries
|
||||
|
||||
### individual.json
|
||||
|
||||
Append the new patch entry preserving file ordering (group by minor version, ascending patch number). Schema:
|
||||
|
||||
```json
|
||||
"magento/project-community-edition:<tag>": {
|
||||
"magento": "magento/project-community-edition:<tag>",
|
||||
"php": <number>,
|
||||
"composer": "<string>",
|
||||
"mysql": "mysql:<ver>" | "mariadb:<ver>",
|
||||
"opensearch": "opensearchproject/opensearch:<ver>",
|
||||
"elasticsearch": "elasticsearch:<ver>",
|
||||
"rabbitmq": "rabbitmq:<ver>-management",
|
||||
"redis": "redis:<ver>",
|
||||
"valkey": "valkey/valkey:<ver>",
|
||||
"varnish": "varnish:<ver>",
|
||||
"nginx": "nginx:<ver>",
|
||||
"os": "ubuntu-latest",
|
||||
"release": "<ISO8601 from tag date>",
|
||||
"eol": "<ISO8601 — see EOL rules below>"
|
||||
}
|
||||
```
|
||||
|
||||
### EOL rules
|
||||
|
||||
- The newest patch on a line gets `eol` set to the line's EOL date from Adobe's lifecycle policy page.
|
||||
- When a newer patch on the same line releases, overwrite the previous patch's `eol` with the newer patch's `release` date. So when adding a new patch, also update the prior patch's `eol` accordingly.
|
||||
- Net effect: at any moment only the latest patch on a line carries the line's lifecycle EOL; every older patch's `eol` equals the release date of its successor.
|
||||
|
||||
### composite.json
|
||||
|
||||
The composite range entry for the affected minor (e.g. `magento/project-community-edition:>=2.4.8 <2.4.9`) should reflect the highest patch's stack. Update its fields to match the new entry if the new tag is now the highest in that minor.
|
||||
|
||||
The rolling entries `magento/project-community-edition` and `magento/project-community-edition:next` must always mirror the system requirements of the highest tag across all minors (i.e. the absolute newest patch you just added, if it is the newest overall). Update PHP, Composer, MySQL, OpenSearch, RabbitMQ, Valkey, Varnish, Nginx, OS, release, eol on both. The `magento` field on `:next` stays `magento/project-community-edition:@alpha`.
|
||||
|
||||
## 5. Verify
|
||||
|
||||
After edits:
|
||||
|
||||
```
|
||||
cd supported-version && npm test
|
||||
```
|
||||
|
||||
All tests must pass before declaring done.
|
||||
|
||||
## Notes
|
||||
|
||||
- Do not remove existing entries — only add or update.
|
||||
- Use the tag's actual publish timestamp from the GitHub API for `release`, not today's date.
|
||||
- If Adobe's docs are ambiguous for a given component, ask the user before guessing.
|
||||
- Preserve the file's existing key ordering and indentation (4 spaces).
|
||||
@@ -0,0 +1,49 @@
|
||||
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
# $$ Code Owners $$
|
||||
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
# $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
|
||||
#
|
||||
# The configuration for Code Owners for graycoreio/magento2-devcontainer.
|
||||
#
|
||||
# For more info see: https://help.github.com/articles/about-codeowners/
|
||||
#
|
||||
|
||||
|
||||
# ================================================
|
||||
# Concepts
|
||||
# ================================================
|
||||
#
|
||||
# A CodeOwner should only review what they are comfortable reviewing. If you're not comfortable, say something.
|
||||
# It is a CodeOwners responsibility to only accept the changes that they understand and deem necessary.
|
||||
# The CodeOwners have final say on whether or not code is accepted.
|
||||
# If multiple CodeOwners are listed, ALL code owners must approve the PR prior to merge.
|
||||
# CodeOwners work in conjunction with Github's "Number of Required Approvals (1)" requirement.
|
||||
|
||||
|
||||
|
||||
# ================================================
|
||||
# GitHub username registry
|
||||
# ================================================
|
||||
|
||||
# damienwebdev - Damien Retzinger
|
||||
|
||||
|
||||
######################################################################################################
|
||||
#
|
||||
# CODEOWNERS rules
|
||||
# -----------------
|
||||
#
|
||||
# All the following rules are applied in the order specified in this file.
|
||||
# The last rule that matches wins!
|
||||
#
|
||||
# See https://git-scm.com/docs/gitignore#_pattern_format for pattern syntax docs.
|
||||
#
|
||||
######################################################################################################
|
||||
|
||||
|
||||
# ================================================
|
||||
# Default Owners
|
||||
# ================================================
|
||||
|
||||
* @damienwebdev
|
||||
@@ -0,0 +1,23 @@
|
||||
name: Cache Magento Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "cache-magento/**"
|
||||
- ".github/workflows/_internal-cache-magento.yaml"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "cache-magento/**"
|
||||
- ".github/workflows/_internal-cache-magento.yaml"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- run: bash cache-magento/test.sh
|
||||
@@ -0,0 +1,108 @@
|
||||
name: Check Store Test
|
||||
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-check-store.yaml"
|
||||
- ".github/workflows/check-store.yaml"
|
||||
- "supported-version/**"
|
||||
- "get-magento-version/**"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-check-store.yaml"
|
||||
- ".github/workflows/check-store.yaml"
|
||||
- "supported-version/**"
|
||||
- "get-magento-version/**"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
id: supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
|
||||
prepare-fixture:
|
||||
needs: compute_matrix
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: ./setup-magento
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
magento_version: ${{ matrix.magento }}
|
||||
mode: extension
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./cache-magento
|
||||
with:
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: true
|
||||
|
||||
- name: Inspect stamp cache contents
|
||||
if: always()
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: |
|
||||
echo "=== top-level vendor/magento ==="
|
||||
ls vendor/magento/ 2>/dev/null | head -30 || echo "(no vendor/magento)"
|
||||
echo
|
||||
echo "=== magento2-base presence ==="
|
||||
if [ -d vendor/magento/magento2-base ]; then
|
||||
echo "PRESENT — file count: $(find vendor/magento/magento2-base -type f | wc -l)"
|
||||
else
|
||||
echo "ABSENT (negation worked)"
|
||||
fi
|
||||
echo
|
||||
echo "=== installed.json mentions magento/magento2-base ==="
|
||||
grep -c '"name": "magento/magento2-base"' vendor/composer/installed.json 2>/dev/null || echo 0
|
||||
|
||||
- run: composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: store-fixture-${{ matrix.version }}
|
||||
path: |
|
||||
${{ steps.setup-magento.outputs.path }}
|
||||
!${{ steps.setup-magento.outputs.path }}/vendor
|
||||
retention-days: 3
|
||||
|
||||
check-store:
|
||||
needs: [compute_matrix, prepare-fixture]
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
fail-fast: false
|
||||
uses: ./.github/workflows/check-store.yaml
|
||||
with:
|
||||
store_artifact_name: store-fixture-${{ matrix.version }}
|
||||
path: "_ghamagento/"
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
stamp: true
|
||||
secrets:
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
- "_test/demo-package/**"
|
||||
- ".github/workflows/_internal-coding-standard.yaml"
|
||||
- "coding-standard/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -16,7 +16,7 @@ on:
|
||||
- "_test/demo-package/**"
|
||||
- ".github/workflows/_internal-coding-standard.yaml"
|
||||
- "coding-standard/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
@@ -32,11 +32,12 @@ on:
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
@@ -50,10 +51,15 @@ jobs:
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
coverage: none
|
||||
|
||||
- uses: './coding-standard'
|
||||
with:
|
||||
version: ${{ github.event.inputs.version || '*' }}
|
||||
path: ${{ github.event.inputs.path || '_test/demo-package' }}
|
||||
composer_version: ${{ matrix.composer }}
|
||||
php_version: ${{ matrix.php }}
|
||||
path: ${{ github.event.inputs.path || '_test/demo-package' }}
|
||||
@@ -8,20 +8,21 @@ on:
|
||||
paths:
|
||||
- ".github/workflows/_internal-get-composer-version.yaml"
|
||||
- "get-composer-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-get-composer-version.yaml"
|
||||
- "get-composer-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
get-composer-version:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set PHP Version
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
|
||||
@@ -7,20 +7,21 @@ on:
|
||||
paths:
|
||||
- ".github/workflows/_internal-get-magento-version.yaml"
|
||||
- "get-magento-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-get-magento-version.yaml"
|
||||
- "get-magento-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
get-magento-version:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set PHP Version
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
@@ -29,15 +30,43 @@ jobs:
|
||||
|
||||
- run: composer create-project --repository-url="https://mirror.mage-os.org" "magento/project-community-edition:2.4.5-p1" ../magento2 --no-install
|
||||
shell: bash
|
||||
name: Create Magento ${{ matrix.magento }} Project
|
||||
name: Create Magento ${{ matrix.magento }} Project
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./get-magento-version
|
||||
id: magento-version
|
||||
with:
|
||||
working-directory: ../magento2
|
||||
|
||||
- name: Fail if key does not match
|
||||
- name: Fail if version does not match
|
||||
if: steps.magento-version.outputs.version != '"2.4.5-p1"'
|
||||
shell: bash
|
||||
run: echo "${{ steps.magento-version.outputs.version }}" && exit 1
|
||||
|
||||
|
||||
- name: Fail if project does not match
|
||||
if: steps.magento-version.outputs.project != 'magento/project-community-edition'
|
||||
shell: bash
|
||||
run: echo "${{ steps.magento-version.outputs.project }}" && exit 1
|
||||
|
||||
get-magento-version-extension:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Create mock extension composer.json
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p /tmp/test-extension
|
||||
echo '{"name":"vendor/module","type":"magento2-module","require":{}}' > /tmp/test-extension/composer.json
|
||||
|
||||
- uses: ./get-magento-version
|
||||
id: ext-version
|
||||
with:
|
||||
working-directory: /tmp/test-extension
|
||||
|
||||
- name: Fail if project is not empty
|
||||
if: steps.ext-version.outputs.project != ''
|
||||
shell: bash
|
||||
run: echo "Expected empty project, got '${{ steps.ext-version.outputs.project }}'" && exit 1
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
name: Installation Test
|
||||
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "_test/demo-package/**"
|
||||
- "installation-test/**"
|
||||
- ".github/workflows/_internal-install.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "_test/demo-package/**"
|
||||
- "installation-test/**"
|
||||
- ".github/workflows/_internal-install.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
|
||||
env:
|
||||
MAGENTO_COMPOSER_REPO: "https://mirror.mage-os.org/"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
id: supported-version
|
||||
- run: echo ${{ steps.supported-version.outputs.matrix }}
|
||||
|
||||
install-test:
|
||||
needs: compute_matrix
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./installation-test
|
||||
with:
|
||||
composer_version: ${{ matrix.composer }}
|
||||
php_version: ${{ matrix.php }}
|
||||
magento_version: ${{ matrix.magento }}
|
||||
package_name: mage-os/magento2-demo-package
|
||||
source_folder: $GITHUB_WORKSPACE/_test/demo-package
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
magento_repository: ${{ env.MAGENTO_COMPOSER_REPO }}
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
- ".github/workflows/_internal-integration.yaml"
|
||||
- ".github/workflows/integration.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -19,19 +19,20 @@ on:
|
||||
- ".github/workflows/_internal-integration.yaml"
|
||||
- ".github/workflows/integration.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
include_services: true
|
||||
id: supported-version
|
||||
integration-workflow:
|
||||
needs: compute_matrix
|
||||
uses: ./.github/workflows/integration.yaml
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
name: Sansec eComscan Security Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-sansec-ecomscan.yaml"
|
||||
- "sansec-ecomscan/**"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-sansec-ecomscan.yaml"
|
||||
- "sansec-ecomscan/**"
|
||||
- "!**/*.md"
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
MAGENTO_COMPOSER_REPO: "https://mirror.mage-os.org/"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
id: supported-version
|
||||
|
||||
run-ecomscan:
|
||||
needs: compute_matrix
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: ./setup-magento
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
mode: extension
|
||||
magento_repository: ${{ env.MAGENTO_COMPOSER_REPO }}
|
||||
magento_version: ${{ matrix.magento }}
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./cache-magento
|
||||
with:
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: true
|
||||
|
||||
- name: Composer install
|
||||
shell: bash
|
||||
run: composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./sansec-ecomscan
|
||||
with:
|
||||
license: ${{ secrets.SANSEC_LICENSE_KEY }}
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
@@ -7,20 +7,21 @@ on:
|
||||
paths:
|
||||
- ".github/workflows/_internal-semver-compare.yaml"
|
||||
- "semver-compare/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- ".github/workflows/_internal-semver-compare.yaml"
|
||||
- "semver-compare/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
semver-compare:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: ./semver-compare
|
||||
id: version-compare-1
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
name: Setup Install Test
|
||||
|
||||
on:
|
||||
workflow_dispatch: {}
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "_test/demo-package/**"
|
||||
- "setup-install/**"
|
||||
- ".github/workflows/_internal-setup-install.yaml"
|
||||
- "supported-version/**"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "_test/demo-package/**"
|
||||
- "setup-install/**"
|
||||
- ".github/workflows/_internal-setup-install.yaml"
|
||||
- "supported-version/**"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
id: supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
include_services: true
|
||||
|
||||
setup-install:
|
||||
needs: compute_matrix
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
fail-fast: false
|
||||
runs-on: ${{ matrix.os }}
|
||||
services: ${{ matrix.services }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: ./setup-magento
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
mode: extension
|
||||
magento_version: ${{ matrix.magento }}
|
||||
magento_repository: "https://mirror.mage-os.org/"
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./cache-magento
|
||||
with:
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: true
|
||||
|
||||
- name: Add extension repository
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer config repositories.local path ${{ github.workspace }}/_test/demo-package
|
||||
|
||||
- name: Get package name
|
||||
id: package
|
||||
run: echo "name=$(jq -r .name ${{ github.workspace }}/_test/demo-package/composer.json)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Require extension
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer require "${{ steps.package.outputs.name }}:@dev" --no-install
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
COMPOSER_MIRROR_PATH_REPOS: 1
|
||||
|
||||
- uses: ./setup-install
|
||||
with:
|
||||
services: ${{ toJSON(matrix.services) }}
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
- "setup-magento/**"
|
||||
- ".github/workflows/_internal-setup-magento.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -17,15 +17,15 @@ on:
|
||||
- "setup-magento/**"
|
||||
- ".github/workflows/_internal-setup-magento.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
|
||||
env:
|
||||
PSEUDO_REPO_FOLDER: ../magento_repo
|
||||
magento_folder: ../magento2
|
||||
magento_folder: _ghamagento
|
||||
MAGENTO_COMPOSER_REPO: "https://mirror.mage-os.org/"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
@@ -37,6 +37,18 @@ jobs:
|
||||
id: supported-version
|
||||
- run: echo ${{ steps.supported-version.outputs.matrix }}
|
||||
|
||||
compute_matrix_latest:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
with:
|
||||
kind: latest
|
||||
id: supported-version
|
||||
|
||||
setup-magento-store:
|
||||
needs: compute_matrix
|
||||
strategy:
|
||||
@@ -46,51 +58,124 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- run: |
|
||||
PSEUDO_STORE_FULL_PATH=$(realpath "${{ env.PSEUDO_REPO_FOLDER }}")
|
||||
echo "PSEUDO_STORE_FULL_PATH=$PSEUDO_STORE_FULL_PATH" >> $GITHUB_ENV
|
||||
name: Generate Full Pseudo Store Path
|
||||
shell: bash
|
||||
|
||||
- name: Set PHP Version
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
|
||||
- uses: actions/cache@v5
|
||||
id: setup-magento-store-cache
|
||||
with:
|
||||
key: setup-magento-ci | ${{ runner.os }} | ${{ matrix.magento }}
|
||||
path: ${{ env.PSEUDO_STORE_FULL_PATH }}
|
||||
|
||||
- run: composer create-project --repository-url="${{ env.MAGENTO_COMPOSER_REPO }}" "${{ matrix.magento }}" "${{ env.PSEUDO_REPO_FOLDER }}" --no-install
|
||||
- run: composer create-project --repository-url="${{ env.MAGENTO_COMPOSER_REPO }}" "${{ matrix.magento }}" "${{ env.magento_folder }}" --no-install
|
||||
name: Create Store to simulate a real Magento store in a real repo.
|
||||
if: steps.setup-magento-store-cache.outputs.cache-hit != 'true'
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./fix-magento-install
|
||||
name: Fix Magento Out of Box Install Issues
|
||||
with:
|
||||
magento_directory: ${{ env.PSEUDO_REPO_FOLDER }}
|
||||
if: steps.setup-magento-store-cache.outputs.cache-hit != 'true'
|
||||
magento_directory: ${{ env.magento_folder }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ env.magento_folder }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./cache-magento
|
||||
with:
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
working-directory: ${{ env.magento_folder }}
|
||||
stamp: true
|
||||
|
||||
- run: composer install
|
||||
shell: bash
|
||||
working-directory: "${{ env.PSEUDO_REPO_FOLDER }}"
|
||||
if: steps.setup-magento-store-cache.outputs.cache-hit != 'true'
|
||||
working-directory: "${{ env.magento_folder }}"
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- run: git init && git config user.email "you@example.com" && git config user.name "Your Name" && git add . && git commit -m "init" && git clean -fdx
|
||||
working-directory: "${{ env.PSEUDO_REPO_FOLDER }}"
|
||||
if: steps.setup-magento-store-cache.outputs.cache-hit != 'true'
|
||||
|
||||
- run: cp -R ${{ env.PSEUDO_REPO_FOLDER }} ${{ env.magento_folder }}
|
||||
- name: Write Magento .gitignore so git clean strips vendor/generated/var from the cached tree
|
||||
working-directory: "${{ env.magento_folder }}"
|
||||
shell: bash
|
||||
run: |
|
||||
cat > .gitignore <<'EOF'
|
||||
/.buildpath
|
||||
/.cache
|
||||
/.metadata
|
||||
/.project
|
||||
/.settings
|
||||
/.vscode
|
||||
atlassian*
|
||||
/nbproject
|
||||
/robots.txt
|
||||
/pub/robots.txt
|
||||
/sitemap
|
||||
/sitemap.xml
|
||||
/pub/sitemap
|
||||
/pub/sitemap.xml
|
||||
/.idea
|
||||
/.gitattributes
|
||||
/app/config_sandbox
|
||||
/app/etc/config.php
|
||||
/app/etc/env.php
|
||||
/app/code/Magento/TestModule*
|
||||
/lib/internal/flex/uploader/.actionScriptProperties
|
||||
/lib/internal/flex/uploader/.flexProperties
|
||||
/lib/internal/flex/uploader/.project
|
||||
/lib/internal/flex/uploader/.settings
|
||||
/lib/internal/flex/varien/.actionScriptProperties
|
||||
/lib/internal/flex/varien/.flexLibProperties
|
||||
/lib/internal/flex/varien/.project
|
||||
/lib/internal/flex/varien/.settings
|
||||
/node_modules
|
||||
/.grunt
|
||||
/Gruntfile.js
|
||||
/package.json
|
||||
/.php_cs
|
||||
/.php_cs.cache
|
||||
/.php-cs-fixer.php
|
||||
/.php-cs-fixer.cache
|
||||
/grunt-config.json
|
||||
/pub/media/*.*
|
||||
!/pub/media/.htaccess
|
||||
/pub/media/attribute/*
|
||||
!/pub/media/attribute/.htaccess
|
||||
/pub/media/analytics/*
|
||||
/pub/media/catalog/*
|
||||
!/pub/media/catalog/.htaccess
|
||||
/pub/media/customer/*
|
||||
!/pub/media/customer/.htaccess
|
||||
/pub/media/downloadable/*
|
||||
!/pub/media/downloadable/.htaccess
|
||||
/pub/media/favicon/*
|
||||
/pub/media/import/*
|
||||
!/pub/media/import/.htaccess
|
||||
/pub/media/logo/*
|
||||
/pub/media/custom_options/*
|
||||
!/pub/media/custom_options/.htaccess
|
||||
/pub/media/theme/*
|
||||
/pub/media/theme_customization/*
|
||||
!/pub/media/theme_customization/.htaccess
|
||||
/pub/media/wysiwyg/*
|
||||
!/pub/media/wysiwyg/.htaccess
|
||||
/pub/media/tmp/*
|
||||
!/pub/media/tmp/.htaccess
|
||||
/pub/media/captcha/*
|
||||
/pub/media/sitemap/*
|
||||
!/pub/media/sitemap/.htaccess
|
||||
/pub/static/*
|
||||
!/pub/static/.htaccess
|
||||
|
||||
/var/*
|
||||
!/var/.htaccess
|
||||
/vendor/*
|
||||
!/vendor/.htaccess
|
||||
/generated/*
|
||||
!/generated/.htaccess
|
||||
.DS_Store
|
||||
EOF
|
||||
|
||||
- run: git init && git config user.email "you@example.com" && git config user.name "Your Name" && git add . && git commit -m "init" && git clean -fdx
|
||||
working-directory: "${{ env.magento_folder }}"
|
||||
|
||||
- uses: ./setup-magento
|
||||
id: setup-magento
|
||||
@@ -100,11 +185,12 @@ jobs:
|
||||
mode: store
|
||||
working-directory: ${{ env.magento_folder }}
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
|
||||
- uses: ./cache-magento
|
||||
with:
|
||||
mode: 'store'
|
||||
composer_cache_key: '${{ matrix.magento }}'
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
working-directory: ${{ env.magento_folder }}
|
||||
stamp: true
|
||||
|
||||
- run: composer install
|
||||
name: Composer install
|
||||
@@ -114,25 +200,35 @@ jobs:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
setup-magento-extension:
|
||||
needs: compute_matrix_latest
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix_latest.outputs.matrix) }}
|
||||
fail-fast: false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: ./setup-magento
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: 8.4
|
||||
tools: composer:v2.8
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
mode: extension
|
||||
magento_repository: ${{ env.MAGENTO_COMPOSER_REPO }}
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
magento_version: magento/project-community-edition:2.4.8-p3
|
||||
magento_version: ${{ matrix.magento }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: ./cache-magento
|
||||
with:
|
||||
mode: 'extension'
|
||||
composer_cache_key: 'magento/project-community-edition:2.4.8-p3'
|
||||
|
||||
composer_cache_key: ${{ matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: true
|
||||
|
||||
- run: composer install
|
||||
name: Composer install
|
||||
shell: bash
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
name: Unit Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "_test/demo-package/**"
|
||||
- ".github/workflows/_internal-unit.yaml"
|
||||
- "unit-test/**"
|
||||
- "!(**/*.md)"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- "_test/demo-package/**"
|
||||
- ".github/workflows/_internal-unit.yaml"
|
||||
- "unit-test/**"
|
||||
- "!(**/*.md)"
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
strategy:
|
||||
matrix:
|
||||
php_version:
|
||||
- 8.2
|
||||
- 8.3
|
||||
- 8.4
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./unit-test
|
||||
with:
|
||||
source_folder: _test/demo-package
|
||||
php_version: ${{ matrix.php_version }}
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
- ".github/workflows/_internal_check_extension.yaml"
|
||||
- ".github/workflows/check-extension.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -19,14 +19,15 @@ on:
|
||||
- ".github/workflows/_internal_check_extension.yaml"
|
||||
- ".github/workflows/check-extension.yaml"
|
||||
- "supported-version/**"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
jobs:
|
||||
compute_matrix:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
@@ -38,3 +39,6 @@ jobs:
|
||||
with:
|
||||
path: _test/demo-package
|
||||
matrix: ${{ needs.compute_matrix.outputs.matrix }}
|
||||
stamp: true
|
||||
secrets:
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
@@ -8,7 +8,7 @@ on:
|
||||
- ".github/workflows/_internal-supported-version.yaml"
|
||||
- "supported-version/**"
|
||||
- "package-lock.json"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
@@ -16,13 +16,14 @@ on:
|
||||
- ".github/workflows/_internal-supported-version.yaml"
|
||||
- "supported-version/**"
|
||||
- "package-lock.json"
|
||||
- "!(**/*.md)"
|
||||
- "!**/*.md"
|
||||
|
||||
jobs:
|
||||
unit-test:
|
||||
if: "!startsWith(github.head_ref, 'release-please')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- run: npm ci
|
||||
shell: bash
|
||||
|
||||
@@ -27,19 +27,38 @@ on:
|
||||
composer_cache_key:
|
||||
type: string
|
||||
required: false
|
||||
default: "_mageos"
|
||||
default: ""
|
||||
description: A key to version the composer cache. Can be incremented if you need to bust the cache.
|
||||
|
||||
stamp:
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
description: "Cache the vendor/ directory in addition to the Composer download cache."
|
||||
|
||||
secrets:
|
||||
composer_auth:
|
||||
required: false
|
||||
description: "Your composer credentials (typically a stringified json object of the contents of your auth.json)"
|
||||
|
||||
jobs:
|
||||
compute_resolved:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
resolved: ${{ steps.resolve.outputs.resolved }}
|
||||
steps:
|
||||
- uses: graycoreio/github-actions-magento2/resolve-check-config@main
|
||||
id: resolve
|
||||
with:
|
||||
kind: extension
|
||||
matrix: ${{ inputs.matrix }}
|
||||
|
||||
unit-test-extension:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_resolved
|
||||
if: ${{ fromJSON(needs.compute_resolved.outputs.resolved)['unit-test-extension'].enabled != false }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(inputs.matrix) }}
|
||||
matrix: ${{ fromJSON(needs.compute_resolved.outputs.resolved)['unit-test-extension'].matrix }}
|
||||
fail-fast: ${{ inputs.fail-fast }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -54,11 +73,6 @@ jobs:
|
||||
magento_repository: ${{ inputs.magento_repository }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
mode: extension
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
|
||||
- name: Add extension repository
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer config repositories.local path ${{ github.workspace }}/${{ inputs.path }}
|
||||
@@ -70,12 +84,26 @@ jobs:
|
||||
- name: Require extension
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer require "${{ steps.package.outputs.name }}:@dev" --no-install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key && format('{0} | {1}', inputs.composer_cache_key, matrix.magento) || matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: ${{ inputs.stamp }}
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
COMPOSER_MIRROR_PATH_REPOS: 1
|
||||
|
||||
- name: Configure phpunit.xml.dist
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
@@ -98,8 +126,10 @@ jobs:
|
||||
|
||||
compile-extension:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_resolved
|
||||
if: ${{ fromJSON(needs.compute_resolved.outputs.resolved)['compile-extension'].enabled != false }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(inputs.matrix) }}
|
||||
matrix: ${{ fromJSON(needs.compute_resolved.outputs.resolved)['compile-extension'].matrix }}
|
||||
fail-fast: ${{ inputs.fail-fast }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
@@ -114,11 +144,6 @@ jobs:
|
||||
magento_repository: ${{ inputs.magento_repository }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
mode: extension
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
|
||||
- name: Add extension repository
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer config repositories.local path ${{ github.workspace }}/${{ inputs.path }}
|
||||
@@ -133,71 +158,68 @@ jobs:
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key && format('{0} | {1}', inputs.composer_cache_key, matrix.magento) || matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: ${{ inputs.stamp }}
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
COMPOSER_MIRROR_PATH_REPOS: 1
|
||||
|
||||
- name: Enable all modules
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: php bin/magento module:enable --all
|
||||
- uses: graycoreio/github-actions-magento2/setup-di-compile@main
|
||||
with:
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
|
||||
- name: Compile
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: php bin/magento setup:di:compile
|
||||
compute_latest_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@main
|
||||
id: supported-version
|
||||
with:
|
||||
kind: latest
|
||||
|
||||
coding-standard:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_latest_matrix
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(inputs.matrix) }}
|
||||
matrix: ${{ fromJSON(needs.compute_latest_matrix.outputs.matrix) }}
|
||||
fail-fast: ${{ inputs.fail-fast }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Get Composer Version
|
||||
uses: graycoreio/github-actions-magento2/get-composer-version@main
|
||||
id: get-composer-version
|
||||
|
||||
- name: Check if allow-plugins option is available for this version of composer
|
||||
uses: graycoreio/github-actions-magento2/semver-compare@main
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
version: 2.2
|
||||
compare_against: ${{ steps.get-composer-version.outputs.version }}
|
||||
id: is-allow-plugins-available
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
coverage: none
|
||||
|
||||
- name: Enable dealerdirect/phpcodesniffer-composer-installer plugin
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true --global
|
||||
if: steps.is-allow-plugins-available.outputs.result < 1
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key && format('{0} | {1}', inputs.composer_cache_key, matrix.magento) || matrix.magento }}
|
||||
|
||||
- name: Install Coding Standard
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: composer require "magento/magento-coding-standard" "magento/php-compatibility-fork"
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- name: Register Coding Standard
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: vendor/bin/phpcs --config-set installed_paths vendor/magento/magento-coding-standard,vendor/magento/php-compatibility-fork
|
||||
|
||||
- name: Coding Standard Check
|
||||
shell: bash
|
||||
run: |
|
||||
if [ -f .phpcs.xml ] || [ -f phpcs.xml ] || [ -f .phpcs.xml.dist ] || [ -f phpcs.xml.dist ]; then
|
||||
./vendor/bin/phpcs .
|
||||
else
|
||||
./vendor/bin/phpcs --standard=Magento2 --ignore=*vendor/* .
|
||||
fi
|
||||
working-directory: ${{ inputs.path }}
|
||||
- uses: graycoreio/github-actions-magento2/coding-standard@main
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
integration_test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_resolved
|
||||
if: ${{ fromJSON(needs.compute_resolved.outputs.resolved)['integration_test'].enabled != false }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(inputs.matrix) }}
|
||||
matrix: ${{ fromJSON(needs.compute_resolved.outputs.resolved)['integration_test'].matrix }}
|
||||
fail-fast: ${{ inputs.fail-fast }}
|
||||
services: ${{ matrix.services }}
|
||||
steps:
|
||||
@@ -213,11 +235,6 @@ jobs:
|
||||
magento_repository: ${{ inputs.magento_repository }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
mode: extension
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
|
||||
- name: Add extension repository
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer config repositories.local path ${{ github.workspace }}/${{ inputs.path }}
|
||||
@@ -232,11 +249,23 @@ jobs:
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- run: composer update --no-install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key && format('{0} | {1}', inputs.composer_cache_key, matrix.magento) || matrix.magento }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: ${{ inputs.stamp }}
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
COMPOSER_MIRROR_PATH_REPOS: 1
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/get-magento-version@main
|
||||
id: magento-version
|
||||
@@ -272,7 +301,7 @@ jobs:
|
||||
run: ../../../vendor/bin/phpunit -c phpunit.xml.dist --testsuite Extension_Integration_Tests
|
||||
|
||||
- name: Upload test sandbox dir
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
if: failure()
|
||||
with:
|
||||
name: sandbox-data-${{ steps.magento-version.outputs.version }}
|
||||
|
||||
@@ -0,0 +1,249 @@
|
||||
name: MageCheck Store
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
path:
|
||||
type: string
|
||||
required: false
|
||||
default: "."
|
||||
description: "The folder of the Magento store that you are testing."
|
||||
|
||||
composer_cache_key:
|
||||
type: string
|
||||
required: false
|
||||
default: "_mageos"
|
||||
description: A key to version the composer cache. Can be incremented if you need to bust the cache.
|
||||
|
||||
store_artifact_name:
|
||||
type: string
|
||||
required: false
|
||||
default: ""
|
||||
description: "If provided, download store files from this artifact instead of using actions/checkout."
|
||||
|
||||
stamp:
|
||||
type: boolean
|
||||
required: false
|
||||
default: false
|
||||
description: "Cache the vendor/ directory in addition to the Composer download cache."
|
||||
|
||||
secrets:
|
||||
composer_auth:
|
||||
required: false
|
||||
description: "Your composer credentials (typically a stringified json object of the contents of your auth.json)"
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
resolved: ${{ steps.resolve.outputs.resolved }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: inputs.store_artifact_name == ''
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
if: inputs.store_artifact_name != ''
|
||||
with:
|
||||
name: ${{ inputs.store_artifact_name }}
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/get-magento-version@main
|
||||
id: get-magento-version
|
||||
with:
|
||||
working-directory: ${{ inputs.path }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@main
|
||||
id: supported-version
|
||||
with:
|
||||
project: ${{ steps.get-magento-version.outputs.supported_version_project }}
|
||||
kind: custom
|
||||
custom_versions: ${{ steps.get-magento-version.outputs.project }}:${{ fromJSON(steps.get-magento-version.outputs.version) }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/resolve-check-config@main
|
||||
id: resolve
|
||||
with:
|
||||
kind: store
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
|
||||
unit-test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_matrix
|
||||
if: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['unit-test'].enabled != false }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['unit-test'].matrix }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: inputs.store_artifact_name == ''
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
if: inputs.store_artifact_name != ''
|
||||
with:
|
||||
name: ${{ inputs.store_artifact_name }}
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/setup-magento@main
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
mode: store
|
||||
working-directory: ${{ inputs.path }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: ${{ inputs.stamp }}
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- name: Configure phpunit.xml.dist
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: |
|
||||
mkdir -p app/code
|
||||
|
||||
cat > /tmp/testsuite.xml << 'EOF'
|
||||
<testsuite name="Store_Unit_Tests">
|
||||
<directory>../../../app/code/*/*/Test/Unit</directory>
|
||||
</testsuite>
|
||||
EOF
|
||||
sed -i '/<testsuites>/r /tmp/testsuite.xml' dev/tests/unit/phpunit.xml.dist
|
||||
|
||||
## PHPUnit 12 (Magento 2.4.9) implicitly enables failOnEmptyTestSuite when --testsuite is passed.
|
||||
## Default it off only when the consumer hasn't set it themselves, so we don't clobber explicit configuration.
|
||||
if ! grep -q 'failOnEmptyTestSuite=' dev/tests/unit/phpunit.xml.dist; then
|
||||
sed -i 's|<phpunit |<phpunit failOnEmptyTestSuite="false" |' dev/tests/unit/phpunit.xml.dist
|
||||
fi
|
||||
|
||||
## Disable allure (See https://github.com/magento/magento2/issues/36702 )
|
||||
sed -i '/<extensions>/,/<\/extensions>/d' dev/tests/unit/phpunit.xml.dist
|
||||
|
||||
- name: Run unit tests
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist --testsuite Store_Unit_Tests
|
||||
|
||||
coding-standard:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_matrix
|
||||
if: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['coding-standard'].enabled != false }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['coding-standard'].matrix }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: inputs.store_artifact_name == ''
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
if: inputs.store_artifact_name != ''
|
||||
with:
|
||||
name: ${{ inputs.store_artifact_name }}
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/setup-magento@main
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
mode: store
|
||||
working-directory: ${{ inputs.path }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: ${{ inputs.stamp }}
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- name: Create default phpcs.xml if none exists
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: |
|
||||
mkdir -p app/code
|
||||
if [ ! -f .phpcs.xml ] && [ ! -f phpcs.xml ] && [ ! -f .phpcs.xml.dist ] && [ ! -f phpcs.xml.dist ]; then
|
||||
cat > phpcs.xml << 'EOF'
|
||||
<ruleset name="Store">
|
||||
<rule ref="Magento2"/>
|
||||
<file>app/code</file>
|
||||
</ruleset>
|
||||
EOF
|
||||
fi
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/coding-standard@main
|
||||
with:
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
smoke-test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_matrix
|
||||
if: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['smoke-test'].enabled != false }}
|
||||
services: ${{ matrix.services }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['smoke-test'].matrix }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
if: inputs.store_artifact_name == ''
|
||||
|
||||
- uses: actions/download-artifact@v8
|
||||
if: inputs.store_artifact_name != ''
|
||||
with:
|
||||
name: ${{ inputs.store_artifact_name }}
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/setup-magento@main
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
mode: store
|
||||
working-directory: ${{ inputs.path }}
|
||||
composer_auth: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: ${{ inputs.stamp }}
|
||||
|
||||
- name: Composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/setup-install@main
|
||||
id: setup-install
|
||||
with:
|
||||
services: ${{ toJSON(matrix.services) }}
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
container_id: ${{ job.services['php-fpm'].id }}
|
||||
extra_args: --magento-init-params=MAGE_MODE=developer
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/configure-service-nginx@main
|
||||
with:
|
||||
container_id: ${{ job.services.nginx.id }}
|
||||
magento_path: ${{ inputs.path }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/smoke-test@main
|
||||
if: contains(fromJSON(needs.compute_matrix.outputs.resolved)['smoke-test'].probes, 'page')
|
||||
with:
|
||||
kind: page
|
||||
|
||||
## graphql is opt-in: editions without GraphQL modules (e.g. mage-os
|
||||
## minimal) have no /graphql endpoint. Enable it per store via
|
||||
## `.github/check-store.json` -> jobs.smoke-test.probes: ["page", "graphql"].
|
||||
- uses: graycoreio/github-actions-magento2/smoke-test@main
|
||||
if: contains(fromJSON(needs.compute_matrix.outputs.resolved)['smoke-test'].probes, 'graphql')
|
||||
with:
|
||||
kind: graphql
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
fail-fast: ${{ inputs.fail-fast }}
|
||||
matrix: ${{ fromJSON(inputs.matrix) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: Set PHP Version
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
|
||||
- name: "Cache Composer Packages"
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
key: "composer | v5 | ${{ inputs.composer_cache_key }} | ${{ hashFiles('composer.lock') }} | ${{ matrix.os }} | ${{ matrix.composer }} | ${{ matrix.php }} | ${{ matrix.magento }}"
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
@@ -140,6 +140,7 @@ jobs:
|
||||
env:
|
||||
COMPOSER_CACHE_DIR: ${{ steps.composer-cache.outputs.dir }}
|
||||
COMPOSER_AUTH: ${{ secrets.composer_auth }}
|
||||
COMPOSER_MIRROR_PATH_REPOS: 1
|
||||
|
||||
- name: Replace Configuration Settings for env
|
||||
working-directory: ${{ inputs.magento_directory }}/dev/tests/integration
|
||||
@@ -181,7 +182,7 @@ jobs:
|
||||
name: Run Integration Tests
|
||||
|
||||
- name: Upload test sandbox dir
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
if: failure()
|
||||
with:
|
||||
name: sandbox-data-${{ steps.magento-version.outputs.version }}
|
||||
|
||||
@@ -4,13 +4,146 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release-mode:
|
||||
description: 'auto = follow conventional commits; rc = bump the rc suffix; graduate = graduate the current rc to a stable release.'
|
||||
type: choice
|
||||
required: false
|
||||
default: auto
|
||||
options:
|
||||
- auto
|
||||
- rc
|
||||
- graduate
|
||||
|
||||
env:
|
||||
RELEASE_BRANCH: release-please--branches--main--components--github-actions-magento2
|
||||
|
||||
jobs:
|
||||
release-please:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
releases_created: ${{ steps.release.outputs.releases_created }}
|
||||
steps:
|
||||
- uses: google-github-actions/release-please-action@v4
|
||||
- id: release
|
||||
uses: googleapis/release-please-action@v5
|
||||
with:
|
||||
token: ${{ secrets.GRAYCORE_GITHUB_TOKEN }}
|
||||
command: manifest
|
||||
default-branch: main
|
||||
config-file: ${{ inputs.release-mode == 'rc' && 'release-please-config.rc.json' || (inputs.release-mode == 'graduate' && 'release-please-config.graduate.json' || 'release-please-config.json') }}
|
||||
|
||||
- name: Check if release branch exists
|
||||
id: branch-check
|
||||
if: steps.release.outputs.releases_created != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GRAYCORE_GITHUB_TOKEN }}
|
||||
run: |
|
||||
if gh api "repos/${{ github.repository }}/git/refs/heads/${{ env.RELEASE_BRANCH }}" --silent 2>/dev/null; then
|
||||
echo "EXISTS=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "EXISTS=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Checkout release PR branch
|
||||
if: steps.branch-check.outputs.EXISTS == 'true'
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
ref: ${{ env.RELEASE_BRANCH }}
|
||||
token: ${{ secrets.GRAYBOT_PIN_BACK_PAT }}
|
||||
|
||||
- name: Pin refs on release PR branch
|
||||
id: pin-refs
|
||||
if: steps.branch-check.outputs.EXISTS == 'true'
|
||||
run: |
|
||||
VERSION="v$(jq -r '."."' .release-please-manifest.json)"
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
sed -i "s|uses: graycoreio/github-actions-magento2/\([^@]*\)@main|uses: graycoreio/github-actions-magento2/\1@${VERSION}|g" \
|
||||
*/action.yml \
|
||||
$(find .github/workflows \( -name "*.yml" -o -name "*.yaml" \) ! -name "release-*" ! -name "_internal*")
|
||||
|
||||
if git diff --quiet; then
|
||||
echo "HAS_CHANGES=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "HAS_CHANGES=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit pinned refs
|
||||
if: steps.pin-refs.outputs.HAS_CHANGES == 'true'
|
||||
env:
|
||||
GRAYBOT_GPG_KEY: ${{ secrets.GRAYBOT_GPG_KEY }}
|
||||
run: |
|
||||
echo "$GRAYBOT_GPG_KEY" | gpg --batch --import
|
||||
export GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{print $2}' | cut -d/ -f2)
|
||||
git config --global user.signingkey $GPG_KEY_ID
|
||||
git config --global commit.gpgSign true
|
||||
git config --global user.email "automation@graycore.io"
|
||||
git config --global user.name "Beep Boop"
|
||||
git add .
|
||||
git commit -m "chore: pin internal action refs to ${{ steps.pin-refs.outputs.VERSION }}"
|
||||
git push origin ${{ env.RELEASE_BRANCH }}
|
||||
|
||||
pinback:
|
||||
needs: release-please
|
||||
if: needs.release-please.outputs.releases_created == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
ref: main
|
||||
token: ${{ secrets.GRAYBOT_PIN_BACK_PAT }}
|
||||
|
||||
- name: Extract version
|
||||
id: version
|
||||
run: |
|
||||
VERSION="v$(jq -r '."."' .release-please-manifest.json)"
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Restore @main refs
|
||||
run: |
|
||||
sed -i "s|uses: graycoreio/github-actions-magento2/\([^@]*\)@[^ #]*|uses: graycoreio/github-actions-magento2/\1@main|g" \
|
||||
*/action.yml \
|
||||
$(find .github/workflows \( -name "*.yml" -o -name "*.yaml" \) ! -name "release-please.yml")
|
||||
|
||||
- name: Show changed files
|
||||
run: git diff
|
||||
|
||||
- name: Check for changes
|
||||
id: changes
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "HAS_CHANGES=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "HAS_CHANGES=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Commit and open pinback PR
|
||||
if: steps.changes.outputs.HAS_CHANGES == 'true'
|
||||
env:
|
||||
GRAYBOT_GPG_KEY: ${{ secrets.GRAYBOT_GPG_KEY }}
|
||||
GH_TOKEN: ${{ secrets.GRAYBOT_PIN_BACK_PAT }}
|
||||
run: |
|
||||
echo "$GRAYBOT_GPG_KEY" | gpg --batch --import
|
||||
export GPG_KEY_ID=$(gpg --list-secret-keys --keyid-format LONG | grep sec | awk '{print $2}' | cut -d/ -f2)
|
||||
git config --global user.signingkey $GPG_KEY_ID
|
||||
git config --global commit.gpgSign true
|
||||
git config --global user.email "automation@graycore.io"
|
||||
git config --global user.name "Beep Boop"
|
||||
BRANCH="chore/pinback-${{ steps.version.outputs.VERSION }}"
|
||||
git checkout -b "$BRANCH"
|
||||
git add .
|
||||
git commit -m "chore: restore internal action refs to @main"
|
||||
git push --force origin "$BRANCH"
|
||||
EXISTING=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number // empty')
|
||||
if [ -z "$EXISTING" ]; then
|
||||
gh pr create \
|
||||
--base main \
|
||||
--head "$BRANCH" \
|
||||
--title "chore: restore internal action refs to @main after ${{ steps.version.outputs.VERSION }}" \
|
||||
--body "Restores all internal \`graycoreio/github-actions-magento2\` action refs from \`${{ steps.version.outputs.VERSION }}\` back to \`@main\`."
|
||||
else
|
||||
echo "PR #$EXISTING already exists for $BRANCH — skipping creation"
|
||||
fi
|
||||
@@ -1,2 +1,3 @@
|
||||
node_modules/
|
||||
.idea/
|
||||
tmp
|
||||
@@ -1 +1 @@
|
||||
{".":"4.0.0"}
|
||||
{".":"8.5.0"}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Project Overview
|
||||
|
||||
`github-actions-magento2` — a GitHub Actions toolkit for Magento 2 development. Provides reusable composite actions and reusable workflows that Magento module and store developers call from their own CI pipelines.
|
||||
|
||||
## Repository Structure
|
||||
|
||||
```
|
||||
.github/workflows/ # Reusable workflows and internal CI workflows
|
||||
_test/demo-package/ # Test fixture used by internal CI workflows
|
||||
docs/ # General documentation
|
||||
other-root-level-folders # Individual GitHub Actions (all are external/public)
|
||||
```
|
||||
|
||||
Most actions are **composite** (bash scripts in `action.yml`). Two are **TypeScript bundled**: `supported-version` and `setup-install`.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
npm ci
|
||||
npm test
|
||||
|
||||
# Run tests for a single package
|
||||
cd actionName && npm test
|
||||
|
||||
# Build a TypeScript action (must be committed after source changes)
|
||||
cd supported-version && npm run build
|
||||
cd setup-install && npm run build
|
||||
```
|
||||
|
||||
Build uses `esbuild` and outputs `dist/index.js`. The `dist/` file **must be committed** — GitHub Actions runs the bundled output directly.
|
||||
|
||||
## Code Style
|
||||
|
||||
- TypeScript with strict settings
|
||||
- ESLint: `eslint:recommended` + `@typescript-eslint/recommended`
|
||||
- No comments unless the "why" is non-obvious
|
||||
- Conventional commits
|
||||
|
||||
## Hard Rules (all agents)
|
||||
|
||||
- Never edit `CHANGELOG.md` — managed by release-please
|
||||
- Never commit TypeScript source changes without also committing the rebuilt `dist/index.js`
|
||||
- Never add external runtime dependencies to TypeScript actions without flagging bundle size impact
|
||||
- Never call `_internal-*` workflows from external repositories
|
||||
|
||||
---
|
||||
|
||||
## @test-agent
|
||||
|
||||
Writes and updates Jest specs for TypeScript actions (`supported-version`, `setup-install`). Scope is limited to `**/*.spec.ts` files.
|
||||
|
||||
### Style
|
||||
|
||||
Test observable behavior, not implementation details. No filesystem mocks — use real temp dirs if needed. No network access.
|
||||
|
||||
```ts
|
||||
import { validateKind } from "./validate-kinds";
|
||||
|
||||
describe('validateKind', () => {
|
||||
it('returns `true` if its a valid kind', () => {
|
||||
expect(validateKind("latest")).toBe(true);
|
||||
});
|
||||
|
||||
it('throws a helpful exception if its an invalid kind', () => {
|
||||
expect(() => validateKind(<any>"taco")).toThrowError();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Never
|
||||
|
||||
- Test implementation details
|
||||
- Mock the filesystem
|
||||
- Write tests that require network access
|
||||
|
||||
---
|
||||
|
||||
## @supported-version-agent
|
||||
|
||||
Manages the Magento/Mage-OS version compatibility data in `supported-version/src/versions/`. Scope is limited to those JSON files.
|
||||
|
||||
### After every edit
|
||||
|
||||
Run `npm test` inside `supported-version/` before declaring done.
|
||||
|
||||
### Never
|
||||
|
||||
- Remove a version entry — only add or mark end-of-life
|
||||
- Guess version compatibility — only use data from official Magento/Mage-OS release notes
|
||||
- Edit TypeScript source in `supported-version/src/`
|
||||
|
||||
---
|
||||
|
||||
## @workflow-agent
|
||||
|
||||
Owns all externally-facing aspects of the repo: every root-level composite action and the three public reusable workflows (`integration.yaml`, `check-extension.yaml`, `check-store.yaml`). Changes here affect downstream callers.
|
||||
|
||||
### Boundaries
|
||||
|
||||
**Free to act** — implementation changes that do not alter the public interface (inputs, outputs, default behavior)
|
||||
|
||||
**Ask first** — any change to inputs, outputs, or default behavior of an external action or reusable workflow
|
||||
|
||||
**Never**
|
||||
- Remove or rename an existing input/output without a major version bump
|
||||
- Change the default value of an existing input
|
||||
- Modify `_internal-*` workflows (out of scope)
|
||||
- Add a runtime dependency to a TypeScript action without flagging bundle size impact
|
||||
+221
@@ -2,6 +2,227 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
## [8.5.0](https://github.com/graycoreio/github-actions-magento2/compare/v8.4.0...v8.5.0) (2026-05-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **setup-install:** run with --no-interaction ([32a5fd2](https://github.com/graycoreio/github-actions-magento2/commit/32a5fd2badfe558e7dced9606765d0d44632c6f0))
|
||||
|
||||
## [8.4.0](https://github.com/graycoreio/github-actions-magento2/compare/v8.3.0...v8.4.0) (2026-05-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove rabbitmq from supported-version for mage-os/minimal ([83f9433](https://github.com/graycoreio/github-actions-magento2/commit/83f9433da0d7f20efbf090fd8ed75a0a39000797))
|
||||
|
||||
## [8.3.0](https://github.com/graycoreio/github-actions-magento2/compare/v8.2.0...v8.3.0) (2026-05-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **check-store:** use the project when computing underlying version requirements ([fa8e597](https://github.com/graycoreio/github-actions-magento2/commit/fa8e59736563d5969f5c8ebaccd23c48f0628721))
|
||||
* **get-magento-version:** add support for MageOS minimal distro ([863444a](https://github.com/graycoreio/github-actions-magento2/commit/863444afbd137d32157392b964f06503f021ee6c))
|
||||
* **get-magento-version:** emit supported-version project name as an output ([1ea5a10](https://github.com/graycoreio/github-actions-magento2/commit/1ea5a10ef67d6fda8d10e078895adc9bea434477))
|
||||
* **supported-version:** add support for MageOS 3 ([1e63c01](https://github.com/graycoreio/github-actions-magento2/commit/1e63c019edb63ee0bcd4576b4125b73520ca8864))
|
||||
* **supported-version:** add support for MageOS Minimal edition ([befe080](https://github.com/graycoreio/github-actions-magento2/commit/befe0807f7636c125d7e650f2d08012b28554a54))
|
||||
|
||||
## [8.2.0](https://github.com/graycoreio/github-actions-magento2/compare/v8.1.0...v8.2.0) (2026-05-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **check-extension:** allow configuraton via .github/check-extension.json ([#269](https://github.com/graycoreio/github-actions-magento2/issues/269)) ([0bf08ef](https://github.com/graycoreio/github-actions-magento2/commit/0bf08ef69291090e5fe3e3d47cb432c6c9107f30))
|
||||
* **resolve-check-config:** defined required integration test services required ([#269](https://github.com/graycoreio/github-actions-magento2/issues/269)) ([35c1ace](https://github.com/graycoreio/github-actions-magento2/commit/35c1ace2bc68be1356dc6565a8a05ff02e33d75d))
|
||||
|
||||
## [8.1.0](https://github.com/graycoreio/github-actions-magento2/compare/v8.0.0...v8.1.0) (2026-05-17)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **check-store:** add smoke-test action and use resolve-check-config ([#255](https://github.com/graycoreio/github-actions-magento2/issues/255)) ([e39dd46](https://github.com/graycoreio/github-actions-magento2/commit/e39dd46f9c53a0d2625cd5d19ad1cf18565b8c5c))
|
||||
* **configure-service-nginx:** add ability to adjust nginx conf after init ([#255](https://github.com/graycoreio/github-actions-magento2/issues/255)) ([0c7d14d](https://github.com/graycoreio/github-actions-magento2/commit/0c7d14d88573d92c81654b1107ef6a9e4d918cff))
|
||||
* **resolve-check-config:** add ability to use a config file to adjust jobs ([#255](https://github.com/graycoreio/github-actions-magento2/issues/255)) ([b98313e](https://github.com/graycoreio/github-actions-magento2/commit/b98313e10044a0a6a04546d3ff8ebe3a3f284f5b))
|
||||
* **setup-install:** add a container_id input to run setup:install against a specific container ([#255](https://github.com/graycoreio/github-actions-magento2/issues/255)) ([6d4ca8d](https://github.com/graycoreio/github-actions-magento2/commit/6d4ca8d669164d840d99e8af721309abb9f204ea))
|
||||
* **smoke-test:** add simple smoke test action ([#255](https://github.com/graycoreio/github-actions-magento2/issues/255)) ([b790da1](https://github.com/graycoreio/github-actions-magento2/commit/b790da18597e58a9013cc0f7e2c923f08c82f813))
|
||||
* **supported-version:** add service_preferences and support for php-fpm and nginx ([#255](https://github.com/graycoreio/github-actions-magento2/issues/255)) ([e89f6ad](https://github.com/graycoreio/github-actions-magento2/commit/e89f6ad2e08fcaa03cba92c8371e60ba67b3cf62))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **check-extension:** only run coding-standard on most recent version of Magento ([#265](https://github.com/graycoreio/github-actions-magento2/issues/265)) ([8e82fcc](https://github.com/graycoreio/github-actions-magento2/commit/8e82fcc89354c83523781c1f5fd4622dec19ca7b))
|
||||
|
||||
## [8.0.0](https://github.com/graycoreio/github-actions-magento2/compare/v8.0.0-rc.2...v8.0.0) (2026-05-14)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* graduate 8.0.0-rc.2 to 8.0.0 ([#262](https://github.com/graycoreio/github-actions-magento2/issues/262)) ([e6bb7be](https://github.com/graycoreio/github-actions-magento2/commit/e6bb7be5248a1431f06c07986066ab154c9d8531))
|
||||
|
||||
## [8.0.0-rc.2](https://github.com/graycoreio/github-actions-magento2/compare/v8.0.0-rc.1...v8.0.0-rc.2) (2026-05-13)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **supported-versions:** forcibly bump all packages to the latest relevant release line of composer for LogLeak
|
||||
* **supported-versions:** This release brings support for the v2.4.9 version of Magento. This also brings backwards-incompatible infrastructure changes for the patch versions of Magento. See https://github.com/graycoreio/github-actions-magento2/pull/258 for more information.
|
||||
|
||||
### Features
|
||||
|
||||
* **check-extension:** pass along COMPOSER_AUTH where needed ([#258](https://github.com/graycoreio/github-actions-magento2/issues/258)) ([c5221f0](https://github.com/graycoreio/github-actions-magento2/commit/c5221f0d68b7ecc892b7718326eabc6f093c108f))
|
||||
* **supported-versions:** forcibly bump all packages to the latest relevant release line of composer for LogLeak ([d1a31d2](https://github.com/graycoreio/github-actions-magento2/commit/d1a31d260dc54556ebd1ea4fb2e1764ad637694a))
|
||||
* **supported-versions:** updates for 2.4.9, 2.4.8-p5, 2.4.7-p19, 2.4.6-p15 ([#258](https://github.com/graycoreio/github-actions-magento2/issues/258)) ([d37f001](https://github.com/graycoreio/github-actions-magento2/commit/d37f001ab6607d2c23751db12d21a7a9e69543f3))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **check-store:** prevent error in phpunit 12 if no tests exists ([#258](https://github.com/graycoreio/github-actions-magento2/issues/258)) ([4fc491b](https://github.com/graycoreio/github-actions-magento2/commit/4fc491bc1a26b7b7089b562db5d4e4a89b6d0744))
|
||||
|
||||
## [8.0.0-rc.1](https://github.com/graycoreio/github-actions-magento2/compare/v8.0.0-rc.0...v8.0.0-rc.1) (2026-05-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **setup-magento:** prevent Magento dir from being mirrored into vendor ([22627e1](https://github.com/graycoreio/github-actions-magento2/commit/22627e100059b090adaf2484a09db2d5568492ce))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **check-extension:** prevent recursively mirroring _ghamagento into _ghamagento ([b0131f0](https://github.com/graycoreio/github-actions-magento2/commit/b0131f0fa08dae3b41c6ae476ae5f81ac654c68b))
|
||||
* **check-store:** only run unit tests for unit tests ([ef06f45](https://github.com/graycoreio/github-actions-magento2/commit/ef06f4566ba2bd9e132d0fe85becb5a96b58aa38))
|
||||
|
||||
## [8.0.0-rc.0](https://github.com/graycoreio/github-actions-magento2/compare/v7.0.0...v8.0.0-rc.0) (2026-05-10)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **setup-magento:** Previously, when using setup-magento in extension mode, the magento 2 repo root was ../magento2 (outside of the extension folder). Due to interactions with `cache-magento` we need to keep magento inside the GITHUB_WORKSPACE (the root repo). We now do this in the `_ghamagento` folder. If you rely on the `steps.setup-magento.outputs.path` nothing changes for you. But, if you hardcoded the path, it's likely broken.
|
||||
|
||||
### Features
|
||||
|
||||
* **cache-magento:** add stamp caching for vendor/ directory ([#245](https://github.com/graycoreio/github-actions-magento2/issues/245)) ([8d00f81](https://github.com/graycoreio/github-actions-magento2/commit/8d00f8149abb5fe9dc9cc87775b108f30284cf21))
|
||||
* **cache-magento:** include runner.os in the cache key ([#245](https://github.com/graycoreio/github-actions-magento2/issues/245)) ([2d7238d](https://github.com/graycoreio/github-actions-magento2/commit/2d7238de14a6ce3657b430ebd89f60b4cc341a09))
|
||||
* **check-extension:** enable stamp caching ([#248](https://github.com/graycoreio/github-actions-magento2/issues/248)) ([baef64b](https://github.com/graycoreio/github-actions-magento2/commit/baef64bc0a235dc92cb81c10afbd22e70e6623f2))
|
||||
* **check-extension:** use setup-di-compile action in compile-extension job ([#240](https://github.com/graycoreio/github-actions-magento2/issues/240)) ([6a520d4](https://github.com/graycoreio/github-actions-magento2/commit/6a520d49fd4ba3f33151dbb8c12dfd3be47630ab))
|
||||
* **check-store:** enable stamp caching ([#247](https://github.com/graycoreio/github-actions-magento2/issues/247)) ([59f87b6](https://github.com/graycoreio/github-actions-magento2/commit/59f87b6b2e4e0007e041c82329291012ee95ce61))
|
||||
* **check-store:** introduce new check-store workflow ([#241](https://github.com/graycoreio/github-actions-magento2/issues/241)) ([d311df7](https://github.com/graycoreio/github-actions-magento2/commit/d311df79661d13ab252eb681600608ed821c78fd))
|
||||
* **get-magento-version:** pull version from lockfile if it exists ([#242](https://github.com/graycoreio/github-actions-magento2/issues/242)) ([87989bb](https://github.com/graycoreio/github-actions-magento2/commit/87989bb250aab72274ad9f71481f70f0a8d8ac1e))
|
||||
* **sansec-ecomscan:** add sansec ecomscan feature ([#235](https://github.com/graycoreio/github-actions-magento2/issues/235)) ([3c0a90f](https://github.com/graycoreio/github-actions-magento2/commit/3c0a90f92ba4e3aaa6854bc98d451fde7340877d))
|
||||
* **sansec-ecomscan:** skip server checks by default ([#238](https://github.com/graycoreio/github-actions-magento2/issues/238)) ([bbd8307](https://github.com/graycoreio/github-actions-magento2/commit/bbd830745f9b752d308f4ef1b8fdc48cea10e5ba))
|
||||
* **setup-di-compile:** restore setup-di-compile as a lean action ([#239](https://github.com/graycoreio/github-actions-magento2/issues/239)) ([212f9a8](https://github.com/graycoreio/github-actions-magento2/commit/212f9a8e86e2c214910e26c3ea19eb90b9aafc4b))
|
||||
* **setup-install:** add new setup-install action ([#237](https://github.com/graycoreio/github-actions-magento2/issues/237)) ([e31f6f6](https://github.com/graycoreio/github-actions-magento2/commit/e31f6f656a2e24afcb95dcc1b4c4dc51e73d00f7))
|
||||
* **setup-magento:** extension working dir changed to _ghamagento folder ([#246](https://github.com/graycoreio/github-actions-magento2/issues/246)) ([a729f8b](https://github.com/graycoreio/github-actions-magento2/commit/a729f8b2fda45af7c4a4cd0bbe32bdf5151bf125))
|
||||
* **setup-magento:** mkdir app/etc in extension mode ([#246](https://github.com/graycoreio/github-actions-magento2/issues/246)) ([c53607c](https://github.com/graycoreio/github-actions-magento2/commit/c53607cca85b77c08a9ae826e5f1365f2b7b9ace))
|
||||
* **supported-version:** dynamically append "version" to matrix ([a7e327d](https://github.com/graycoreio/github-actions-magento2/commit/a7e327d44f6dbca270be5f5c5488498f8ba27b2b))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **coding-standard:** use exactly phpcs.xml if exists ([#243](https://github.com/graycoreio/github-actions-magento2/issues/243)) ([a1c6246](https://github.com/graycoreio/github-actions-magento2/commit/a1c6246c7834203379f25acb03ba8ad7ad42c859))
|
||||
* **fix-magento-install:** remove deprecated set-output ([c115395](https://github.com/graycoreio/github-actions-magento2/commit/c115395583913b1beb539aa514a305d8dcbb9364))
|
||||
|
||||
## [7.0.0](https://github.com/graycoreio/github-actions-magento2/compare/v7.0.0-rc.0...v7.0.0) (2026-04-29)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **supported-version:** update for Mage-OS 2.2.2 ([#317](https://github.com/graycoreio/github-actions-magento2/issues/317)) ([bbecc7f](https://github.com/graycoreio/github-actions-magento2/commit/bbecc7f5f9e4ddfdf5b41eb17fac6db1b30b56f0))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **cache-magento:** address `set-output` deprecation ([#231](https://github.com/graycoreio/github-actions-magento2/issues/231)) ([771dd05](https://github.com/graycoreio/github-actions-magento2/commit/771dd054395a0e0a33e2d712d9793ca8322173e9))
|
||||
* **supported-version:** filter uninstallable versions from usable kind ([#319](https://github.com/graycoreio/github-actions-magento2/issues/319)) ([f803617](https://github.com/graycoreio/github-actions-magento2/commit/f8036173e143ab5d13147c136e0d9e0c6bbb829b))
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* promote release 7.0.0 ([90babb1](https://github.com/graycoreio/github-actions-magento2/commit/90babb16bfb28ca1953c95edb2301c9090b52f67))
|
||||
|
||||
## [7.0.0-rc.0](https://github.com/graycoreio/github-actions-magento2/compare/v6.0.0...v7.0.0-rc.0) (2026-04-28)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **coding-standard:** Much of the "setup" that's built-into the command is removed in favor of a leaner action. This also includes the "on PR, only diff PR contents" behavior. This can be restored, but it shouldn't be the default and should be done as an input.
|
||||
* **coding-standard-baseline:** remove coding-standard-baseline action ([#223](https://github.com/graycoreio/github-actions-magento2/issues/223))
|
||||
* **install-test:** You should rely on [Check Extension](https://github.com/graycoreio/github-actions-magento2/blob/main/.github/workflows/check-extension-README.md) instead.
|
||||
* **unit-test:** remove unit-test action ([#221](https://github.com/graycoreio/github-actions-magento2/issues/221))
|
||||
* **supported-version:** `include_services` now defaults to `true`. Callers that strictly validate the matrix schema and do not expect a `services` key must explicitly pass `include_services: false`.
|
||||
|
||||
### Features
|
||||
|
||||
* **coding-standard-baseline:** remove coding-standard-baseline action ([#223](https://github.com/graycoreio/github-actions-magento2/issues/223)) ([953de84](https://github.com/graycoreio/github-actions-magento2/commit/953de845ebf7b5d2c9a24670b380c016bd6efdcd))
|
||||
* **coding-standard:** add missing composer_auth to require of magento-coding-standard ([3fad3a8](https://github.com/graycoreio/github-actions-magento2/commit/3fad3a89954be09a0f11f04a6c1c7d927fc872eb))
|
||||
* **coding-standard:** remove pr-diff feature and built-in php setup ([#224](https://github.com/graycoreio/github-actions-magento2/issues/224)) ([d5c744e](https://github.com/graycoreio/github-actions-magento2/commit/d5c744e15544e249f79fa486a073d7020635e48a))
|
||||
* **coding-standard:** skip composer install if the coding is already installed ([e1a8a81](https://github.com/graycoreio/github-actions-magento2/commit/e1a8a81488c77144786427ff63a99f93cd17b897))
|
||||
* **install-test:** remove install test ([#222](https://github.com/graycoreio/github-actions-magento2/issues/222)) ([de415ea](https://github.com/graycoreio/github-actions-magento2/commit/de415eaff54507ca24cbecf8916fd1526beb0186))
|
||||
* **unit-test:** remove unit-test action ([#221](https://github.com/graycoreio/github-actions-magento2/issues/221)) ([98923b2](https://github.com/graycoreio/github-actions-magento2/commit/98923b24c58899779a6a6367e3863d718b09bb8d))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **check-extension:** mirror path repos to prevent symlink errors with template files ([#218](https://github.com/graycoreio/github-actions-magento2/issues/218)) ([d80befb](https://github.com/graycoreio/github-actions-magento2/commit/d80befbe9b26dfa37af117775544c85ea36b7127)), closes [#217](https://github.com/graycoreio/github-actions-magento2/issues/217)
|
||||
* **check-extension:** probe vendor dir for MageOS/Magento standards when running phpcs ([#216](https://github.com/graycoreio/github-actions-magento2/issues/216)) ([7799f0f](https://github.com/graycoreio/github-actions-magento2/commit/7799f0f9bf788545bc36924b6528c09c6a8bb09a)), closes [#213](https://github.com/graycoreio/github-actions-magento2/issues/213)
|
||||
* **supported-version:** default include_services to true ([#215](https://github.com/graycoreio/github-actions-magento2/issues/215)) ([b510ea2](https://github.com/graycoreio/github-actions-magento2/commit/b510ea21e38c97a4852776fc4e57fbcf9917fa9f)), closes [#214](https://github.com/graycoreio/github-actions-magento2/issues/214)
|
||||
|
||||
|
||||
### Miscellaneous Chores
|
||||
|
||||
* release 7.0.0-rc.0 ([4001e81](https://github.com/graycoreio/github-actions-magento2/commit/4001e8118b6da28d7c9fd18d3ab127cee03681d3))
|
||||
|
||||
## [6.0.0](https://github.com/graycoreio/github-actions-magento2/compare/v5.1.0...v6.0.0) (2026-03-11)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* **supported-version:** Adobe has dropped support for elasticsearch and redis in their latest releases of v2.4.8.
|
||||
|
||||
### Features
|
||||
|
||||
* **supported-version:** add support for MageOS 2.2.0 ([b4526db](https://github.com/graycoreio/github-actions-magento2/commit/b4526dbb52f59ad79b07fedb5fe487424c0b4dea))
|
||||
* **supported-version:** update for Magento v2.4.8-p4 release ([e6be791](https://github.com/graycoreio/github-actions-magento2/commit/e6be791eed5d2b4f83bb56391e7eab39c52eed59))
|
||||
* **supported-version:** upgrade opensearch to 2.19.5 ([7e40a62](https://github.com/graycoreio/github-actions-magento2/commit/7e40a62efaff0c31fab1284980fc5400997b211f))
|
||||
|
||||
## [5.1.0](https://github.com/graycoreio/github-actions-magento2/compare/v5.0.0...v5.1.0) (2026-02-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **supported-version:** backport composer 2.9.3 to older mage-os verisons ([48902e8](https://github.com/graycoreio/github-actions-magento2/commit/48902e8e6a748a1328a0e50eff32e717a560975c))
|
||||
* **supported-version:** bump all composer versions to latest supported version ([c26e84f](https://github.com/graycoreio/github-actions-magento2/commit/c26e84f69361cd53dce853b415656f3af9b44427))
|
||||
* **supported-version:** bump all nginx versions to latest supported version ([c19912d](https://github.com/graycoreio/github-actions-magento2/commit/c19912dc4bfc83f4649bbd6bff8b8e9366384906))
|
||||
* **supported-versions:** upgrade 2.4.8-p2/p3 to opensearch 3 ([d29e574](https://github.com/graycoreio/github-actions-magento2/commit/d29e57447582250203ee5cbad561306ca6080ffa))
|
||||
* **supported-version:** updated matrix for Mage-OS 2.1.0 ([07f8953](https://github.com/graycoreio/github-actions-magento2/commit/07f89530df8396d359c043c6b3a8b429a67465a8))
|
||||
* **supported-version:** upgrade to compsoer 2.9.5 ([7e70ee9](https://github.com/graycoreio/github-actions-magento2/commit/7e70ee93efb85c48ef312cf4f796bc90acc1b9cf))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **supported-version:** pin specific composer 2 versions for historic Magento releases ([505179c](https://github.com/graycoreio/github-actions-magento2/commit/505179ce7bdf1b41472d9ba735cc36002b84e2a0))
|
||||
* using `latest` accidentally output two versions for Magento Open Source ([34ddee6](https://github.com/graycoreio/github-actions-magento2/commit/34ddee6aef5e21f1e4bfa992ff333031b7552c35))
|
||||
|
||||
## [5.0.0](https://github.com/graycoreio/github-actions-magento2/compare/v4.0.1...v5.0.0) (2026-02-18)
|
||||
|
||||
|
||||
### ⚠ BREAKING CHANGES
|
||||
|
||||
* remove unmaintained setup-di-compile action
|
||||
|
||||
### Features
|
||||
|
||||
* remove unmaintained setup-di-compile action ([7b5ccf7](https://github.com/graycoreio/github-actions-magento2/commit/7b5ccf7d9d67da8c67e77b222b89b0abf332b183))
|
||||
* use actions/cache@v5 ([86b01b1](https://github.com/graycoreio/github-actions-magento2/commit/86b01b17faf443802bdf827fdbb706c55ae7e3fb))
|
||||
* use actions/checkout@v6 ([c2c3755](https://github.com/graycoreio/github-actions-magento2/commit/c2c375572967ee6ff8afc3a406b8d5a02880159e))
|
||||
* use actions/upload-artifact@v6 ([5f3ba73](https://github.com/graycoreio/github-actions-magento2/commit/5f3ba73bc67a5c09e22f83c6e51421596103e0ce))
|
||||
|
||||
## [4.0.1](https://github.com/graycoreio/github-actions-magento2/compare/v4.0.0...v4.0.1) (2025-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **supported-version:** handle semver-ish values from old magento verisons ([7c0bc65](https://github.com/graycoreio/github-actions-magento2/commit/7c0bc65842e0e866cd957a44f879d37d04d11dce))
|
||||
|
||||
## [4.0.0](https://github.com/graycoreio/github-actions-magento2/compare/v3.0.0...v4.0.0) (2025-12-15)
|
||||
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<div align="center">
|
||||
|
||||

|
||||
[](https://github.com/graycoreio/github-actions-magento2/actions/workflows/_internal-unit.yaml)
|
||||
[](https://github.com/graycoreio/github-actions-magento2/actions/workflows/_internal-integration.yaml)
|
||||
[](https://github.com/graycoreio/github-actions-magento2/actions/workflows/_internal-install.yaml)
|
||||
[](https://github.com/graycoreio/github-actions-magento2/actions/workflows/_internal-integration.yaml)
|
||||
[](https://github.com/graycoreio/github-actions-magento2/actions/workflows/_internal_check_extension.yaml)
|
||||
[](https://github.com/graycoreio/github-actions-magento2/actions/workflows/_internal-check-store.yaml)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -17,20 +17,29 @@ Opinionated Github Actions and Workflows to make building, testing, and maintain
|
||||
|
||||
## Workflows
|
||||
|
||||
If you are new here, start with a reusable workflow. They are pre-built CI pipelines that you can adopt in minutes — no deep knowledge of the individual actions required. Pick the one that matches your project type and call it from your own workflow file.
|
||||
|
||||
| Workflow Name | Description |
|
||||
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
||||
| [Integration Test](./.github/workflows/integration-README.md) | A Github Workflow that runs the Integration Tests of a Magento Package |
|
||||
| [MageCheck Extension](./.github/workflows/check-extension-README.md) | A Github Workflow that runs various kinds of quality checks for a Magento Extension. |
|
||||
| [Integration Test](./docs/workflows/integration.md) | **Deprecated** — use MageCheck Extension instead. A Github Workflow that runs the Integration Tests of a Magento Package. |
|
||||
| [MageCheck Extension](./docs/workflows/check-extension.md) | A Github Workflow that runs various kinds of quality checks for a Magento Extension. |
|
||||
| [MageCheck Store](./docs/workflows/check-store.md) | A Github Workflow that runs various kinds of quality checks for a Magento Store. |
|
||||
|
||||
## Actions
|
||||
|
||||
| Action Name | Description |
|
||||
| ------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
||||
| [Unit Test](./unit-test/README.md) | A Github Action that runs the Unit Tests a Magento Package |
|
||||
| [Fix Magento Install](./fix-magento-install/README.md) | A Github Action that fixes Magento before `composer install` |
|
||||
| [Cache Magento](./cache-magento/README.md) | A Github Action that creates a composer cache for a Magento extension or store. |
|
||||
| [Setup Magento](./setup-magento/README.md) | A Github Action that sets up Magento before `composer install` for an extension or store. |
|
||||
| [Get Magento Version](./get-magento-version/README.md) | A Github Action that computes the installed Magento version. |
|
||||
| [Installation Test](./installation-test/README.md) | A Github Action that tests the installability of a Magento Package |
|
||||
| [Semver Compare](./semver-compare/README.md) | A Github Action that semantically compares two versions |
|
||||
| [Supported Version](./supported-version/README.md) | A Github Action that computes the currently supported Github Actions Matrix for Magento 2 |
|
||||
If the reusable workflows do not fit your needs, the individual actions are the building blocks they are composed from. Use these when you need full control over your pipeline.
|
||||
|
||||
|
||||
| Action Name | Description |
|
||||
| ------------------------------------------------------------ | ----------------------------------------------------------------------------------------- |
|
||||
| [Fix Magento Install](./fix-magento-install/README.md) | A Github Action that fixes Magento before `composer install` |
|
||||
| [Cache Magento](./cache-magento/README.md) | A Github Action that creates a composer cache for a Magento extension or store. |
|
||||
| [Setup Magento](./setup-magento/README.md) | A Github Action that sets up Magento before `composer install` for an extension or store. |
|
||||
| [Get Magento Version](./get-magento-version/README.md) | A Github Action that computes the installed Magento version. |
|
||||
| [Get Composer Version](./get-composer-version/README.md) | A Github Action that computes an installed Composer version. |
|
||||
| [Coding Standard](./coding-standard/README.md) | A Github Action that runs the Magento Coding Standard. |
|
||||
| [Semver Compare](./semver-compare/README.md) | A Github Action that semantically compares two versions |
|
||||
| [Supported Version](./supported-version/README.md) | A Github Action that computes the currently supported Github Actions Matrix for Magento 2 |
|
||||
| [Setup Install](./setup-install/README.md) | A Github Action that runs `bin/magento setup:install` from the supported-version services matrix |
|
||||
| [Setup DI Compile](./setup-di-compile/README.md) | A Github Action that enables all modules and runs `bin/magento setup:di:compile` |
|
||||
| [Sansec eComscan](./sansec-ecomscan/README.md) | A Github Action that runs the Sansec eComscan security scanner. |
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Graycore\DemoPackage\Test\Integration;
|
||||
|
||||
use Magento\Framework\View\Element\Template;
|
||||
use Magento\TestFramework\Helper\Bootstrap;
|
||||
|
||||
/**
|
||||
* Fails when the extension is installed as a symlink (default Composer path repo behavior)
|
||||
* because Magento's template engine cannot resolve .phtml files through symlinks.
|
||||
* Requires COMPOSER_MIRROR_PATH_REPOS=1 during composer install.
|
||||
*/
|
||||
class TemplateRenderTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @magentoAppArea frontend
|
||||
*/
|
||||
public function testTemplateRendersWithoutSymlinkError()
|
||||
{
|
||||
$block = Bootstrap::getObjectManager()->create(Template::class);
|
||||
$block->setTemplate('Graycore_DemoPackage::demo.phtml');
|
||||
$this->assertNotEmpty($block->toHtml());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
<?php /** @var \Magento\Framework\View\Element\Template $block */ ?>
|
||||
<div>demo</div>
|
||||
+65
-29
@@ -4,38 +4,74 @@ A Github Action that creates a composer cache for a Magento extension or store.
|
||||
|
||||
## Inputs
|
||||
|
||||
|
||||
See the [action.yml](./action.yml)
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
| ------------------ | -------------------------------------------------------------------------------------- | -------- | ------------ |
|
||||
| composer_cache_key | A key to version the composer cache. Can be incremented if you need to bust the cache. | false | '__mageos' |
|
||||
| mode | "The mode for setup, one of: `extension` or `store`." | true | N/A |
|
||||
| Input | Description | Required | Default |
|
||||
| -------------------- | -------------------------------------------------------------------------------------- | -------- | ---------- |
|
||||
| `composer_cache_key` | A key to version the composer cache. Can be incremented if you need to bust the cache. | false | `__mageos` |
|
||||
| `working-directory` | The directory where Magento is installed (location of `vendor/` and `composer.lock`). | false | `.` |
|
||||
| `stamp` | Cache the `vendor/` directory in addition to the Composer download cache. | false | `false` |
|
||||
|
||||
### Usage
|
||||
## Cache keys
|
||||
|
||||
The download cache key has the format:
|
||||
|
||||
```
|
||||
composer | v5.8 | <os> | <composer_cache_key> | <composer-version> | <php-version>
|
||||
```
|
||||
|
||||
When `stamp: true`, the `vendor/` cache key has the format:
|
||||
|
||||
```
|
||||
composer | stamp | v5.8 | <os> | <composer_cache_key> | <composer-version> | <php-version> | <composer.lock-hash>
|
||||
```
|
||||
|
||||
The `composer.lock` hash is derived from `working-directory/composer.lock` using `hashFiles`. The download key also gains the hash suffix when a Magento product package is detected at `working-directory`.
|
||||
|
||||
## Usage
|
||||
|
||||
### Extension (download cache only)
|
||||
|
||||
```yml
|
||||
name: Magento Cache
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
showcase_cache:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
mode: 'store'
|
||||
id: cache-magento
|
||||
|
||||
- run: composer install
|
||||
shell: bash
|
||||
name: Composer install
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
```
|
||||
|
||||
### Extension or store (download + vendor stamp cache)
|
||||
|
||||
```yml
|
||||
- uses: graycoreio/github-actions-magento2/setup-magento@v8.5.0 # x-release-please-version
|
||||
id: setup-magento
|
||||
with:
|
||||
mode: extension # or store
|
||||
# ...
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
composer_cache_key: ${{ inputs.composer_cache_key }}
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
stamp: true
|
||||
|
||||
- run: composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
```
|
||||
|
||||
### Stamp Mode
|
||||
|
||||
On a warm cache hit, `composer install` completes in ~0s because `vendor/` is already present — Composer sees everything installed and exits immediately. For a full Magento install this saves 2–5 minutes of package extraction per job.
|
||||
|
||||
The trade-off is size. The `vendor/` directory for a Magento project runs 300–600 MB, so a frequent cache miss means you are consistently paying the upload cost without recouping it on the next run.
|
||||
|
||||
As such, use `stamp: true` when `composer.lock` is stable across most runs — a store on a release branch, or extension CI against a pinned Magento version. Skip it when the lock changes often or when runner storage is constrained.
|
||||
|
||||
> [!WARNING]
|
||||
> **Dependabot / Renovate:** Each time a Dependabot or Renovate PR is merged, the remaining open PRs rebase and each produces a new `composer.lock`. This cascades into a large number of unique cache entries, inflating storage costs without delivering proportional compute savings — because automated PRs are not waiting on fast feedback. The fix is to disable stamp caching for automated dependency PRs entirely:
|
||||
>
|
||||
> ```yml
|
||||
> - uses: graycoreio/github-actions-magento2/cache-magento@v8.5.0 # x-release-please-version
|
||||
> with:
|
||||
> stamp: ${{ github.actor != 'dependabot[bot]' }}
|
||||
> ```
|
||||
>
|
||||
> If you use Renovate, check its bot account name and adjust the condition accordingly. Dependabot PRs will pay full `composer install` time on every run, which is acceptable — nobody is waiting on them.
|
||||
|
||||
@@ -7,15 +7,31 @@ inputs:
|
||||
required: false
|
||||
default: "__mageos"
|
||||
description: A key to version the composer cache. Can be incremented if you need to bust the cache.
|
||||
|
||||
mode:
|
||||
required: true
|
||||
description: "The mode for setup, one of: `extension` or `store`."
|
||||
working-directory:
|
||||
required: false
|
||||
default: "."
|
||||
description: "The working directory where Magento is installed (location of vendor/ and composer.lock)"
|
||||
stamp:
|
||||
required: false
|
||||
default: "false"
|
||||
description: "Cache the vendor/ directory in addition to the Composer download cache"
|
||||
exclude-from-stamp:
|
||||
required: false
|
||||
default: ""
|
||||
description: |
|
||||
Newline-separated list of Composer package names to exclude from the stamp cache (e.g. magento/module-foo).
|
||||
magento/magento2-base and mage-os/magento2-base are always excluded regardless of this input.
|
||||
|
||||
outputs:
|
||||
cache-hit:
|
||||
description: "A boolean value to indicate an exact match was found for the key"
|
||||
value: ${{ steps.cache-magento-cache.outputs.cache-hit }}
|
||||
key:
|
||||
description: "The cache key used for the Composer download cache"
|
||||
value: ${{ steps.cache-magento-keys.outputs.download-key }}
|
||||
stamp-key:
|
||||
description: "The cache key used for the vendor/ stamp cache (only set when stamp: true)"
|
||||
value: ${{ steps.cache-magento-keys.outputs.stamp-key }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
@@ -26,22 +42,85 @@ runs:
|
||||
run: |
|
||||
echo "dir=$(composer config cache-files-dir --global)" >> $GITHUB_OUTPUT
|
||||
|
||||
- run: echo "::set-output name=version::$(php -v | awk 'NR==1{print $2}')"
|
||||
- run: echo "version=$(php -v | awk 'NR==1{print $2}')" >> "$GITHUB_OUTPUT"
|
||||
shell: bash
|
||||
id: cache-magento-get-php-version
|
||||
|
||||
- run: echo "::set-output name=version::$(composer --version | awk '{print $3}')"
|
||||
- run: echo "version=$(composer --version | awk '{print $3}')" >> "$GITHUB_OUTPUT"
|
||||
shell: bash
|
||||
name: Compute Composer Version
|
||||
id: cache-magento-get-composer-version
|
||||
|
||||
- name: Validate working-directory is inside GITHUB_WORKSPACE
|
||||
if: inputs.stamp == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
WORKING_DIR="$(realpath '${{ inputs.working-directory }}')"
|
||||
WORKSPACE="$(realpath '${{ github.workspace }}')"
|
||||
if [[ "$WORKING_DIR" != "$WORKSPACE"* ]]; then
|
||||
echo "::error::cache-magento: working-directory '${{ inputs.working-directory }}' resolves outside GITHUB_WORKSPACE. You cannot use the `stamp` cache in folders outside the workspace."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/get-magento-version@main
|
||||
id: cache-magento-get-magento-version
|
||||
with:
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
|
||||
- name: Validate composer.lock exists for stamp cache (store mode)
|
||||
if: inputs.stamp == 'true' && steps.cache-magento-get-magento-version.outputs.project != ''
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ ! -f "${{ inputs.working-directory }}/composer.lock" ]]; then
|
||||
echo "::error::cache-magento: stamp: true on a store requires a '${{ inputs.working-directory }}/composer.lock' to exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Compute cache keys
|
||||
id: cache-magento-keys
|
||||
shell: bash
|
||||
run: |
|
||||
bash "${{ github.action_path }}/compute-cache-keys.sh" \
|
||||
"${{ inputs.composer_cache_key }}" \
|
||||
"${{ runner.os }}" \
|
||||
"${{ steps.cache-magento-get-php-version.outputs.version }}" \
|
||||
"${{ steps.cache-magento-get-composer-version.outputs.version }}" \
|
||||
"${{ steps.cache-magento-get-magento-version.outputs.project }}" \
|
||||
"${{ hashFiles(format('{0}/composer.lock', inputs.working-directory)) }}" \
|
||||
>> $GITHUB_OUTPUT
|
||||
|
||||
- name: "Cache Composer Packages"
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v5
|
||||
id: cache-magento-cache
|
||||
with:
|
||||
key: "composer | v5.8 | ${{ inputs.composer_cache_key }} | ${{ steps.cache-magento-get-composer-version.outputs.version }} | ${{ steps.cache-magento-get-php-version.outputs.version }}"
|
||||
key: ${{ steps.cache-magento-keys.outputs.download-key }}
|
||||
restore-keys: |
|
||||
${{ steps.cache-magento-keys.outputs.download-restore-key }}
|
||||
path: ${{ steps.cache-magento-composer-cache.outputs.dir }}
|
||||
|
||||
- name: Compute stamp paths
|
||||
id: cache-magento-stamp-paths
|
||||
if: inputs.stamp == 'true'
|
||||
shell: bash
|
||||
env:
|
||||
EXCLUDE_FROM_STAMP: ${{ inputs.exclude-from-stamp }}
|
||||
WORKING_DIR: ${{ inputs.working-directory }}
|
||||
run: |
|
||||
PATHS=$(bash "${{ github.action_path }}/compute-stamp-paths.sh" "$(realpath "$WORKING_DIR")" "$EXCLUDE_FROM_STAMP")
|
||||
{
|
||||
echo "paths<<EOF"
|
||||
echo "$PATHS"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: "Cache Vendor (Stamp)"
|
||||
uses: actions/cache@v5
|
||||
if: inputs.stamp == 'true'
|
||||
with:
|
||||
key: ${{ steps.cache-magento-keys.outputs.stamp-key }}
|
||||
path: |
|
||||
${{ steps.cache-magento-stamp-paths.outputs.paths }}
|
||||
|
||||
branding:
|
||||
icon: "code"
|
||||
color: "green"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env bash
|
||||
# Args: composer_cache_key os php_version composer_version project lock_hash
|
||||
COMPOSER_CACHE_KEY="$1"
|
||||
OS="$2"
|
||||
PHP_VERSION="$3"
|
||||
COMPOSER_VERSION="$4"
|
||||
PROJECT="$5"
|
||||
LOCK_HASH="${6:-}"
|
||||
|
||||
MODE="extension"
|
||||
SUFFIX=""
|
||||
if [ -n "$PROJECT" ]; then
|
||||
MODE="store"
|
||||
[ -n "$LOCK_HASH" ] && SUFFIX=" | $LOCK_HASH"
|
||||
fi
|
||||
|
||||
BASE="composer | v5.8 | ${OS} | ${MODE} | ${COMPOSER_CACHE_KEY} | ${COMPOSER_VERSION} | ${PHP_VERSION}"
|
||||
echo "download-key=${BASE}${SUFFIX}"
|
||||
echo "download-restore-key=${BASE}"
|
||||
echo "stamp-key=composer | stamp | v5.8 | ${OS} | ${MODE} | ${COMPOSER_CACHE_KEY} | ${COMPOSER_VERSION} | ${PHP_VERSION}${SUFFIX}"
|
||||
Executable
+18
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env bash
|
||||
# Args: working_directory exclude_from_stamp
|
||||
# working_directory: absolute path (caller is responsible for realpath resolution)
|
||||
# exclude_from_stamp: newline-separated list of composer package names to exclude
|
||||
WORKING_DIR="$1"
|
||||
EXCLUDE_FROM_STAMP="${2:-}"
|
||||
VENDOR="${WORKING_DIR}/vendor"
|
||||
|
||||
PATHS="${VENDOR}/**"$'\n'"!${VENDOR}/**/"$'\n'"!${VENDOR}/magento/magento2-base"$'\n'"!${VENDOR}/magento/magento2-base/**"$'\n'"!${VENDOR}/mage-os/magento2-base"$'\n'"!${VENDOR}/mage-os/magento2-base/**"
|
||||
|
||||
while IFS= read -r pkg; do
|
||||
pkg="${pkg#"${pkg%%[![:space:]]*}"}"
|
||||
pkg="${pkg%"${pkg##*[![:space:]]}"}"
|
||||
[[ -z "$pkg" ]] && continue
|
||||
PATHS="${PATHS}"$'\n'"!${VENDOR}/${pkg}"$'\n'"!${VENDOR}/${pkg}/**"
|
||||
done <<< "$EXCLUDE_FROM_STAMP"
|
||||
|
||||
echo "$PATHS"
|
||||
Generated
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "magento/product-community-edition",
|
||||
"version": "2.4.7"
|
||||
}
|
||||
],
|
||||
"packages-dev": []
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SCRIPT="$SCRIPT_DIR/compute-cache-keys.sh"
|
||||
SCRIPT_STAMP="$SCRIPT_DIR/compute-stamp-paths.sh"
|
||||
LOCK_HASH=$(sha256sum "$SCRIPT_DIR/fixtures/composer.lock" | cut -d' ' -f1)
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
assert_eq() {
|
||||
local label="$1" expected="$2" actual="$3"
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo "PASS: $label"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "FAIL: $label"
|
||||
echo " expected: $expected"
|
||||
echo " actual: $actual"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
field() {
|
||||
echo "$1" | grep "^${2}=" | cut -d= -f2-
|
||||
}
|
||||
|
||||
# Extension mode: no project resolved, mode derived as "extension", no lock suffix
|
||||
OUT=$(bash "$SCRIPT" "_mageos" "Linux" "8.3.0" "2.2.6" "" "")
|
||||
assert_eq "extension: download-key" \
|
||||
"composer | v5.8 | Linux | extension | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" download-key)"
|
||||
assert_eq "extension: download-restore-key" \
|
||||
"composer | v5.8 | Linux | extension | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" download-restore-key)"
|
||||
assert_eq "extension: stamp-key" \
|
||||
"composer | stamp | v5.8 | Linux | extension | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" stamp-key)"
|
||||
|
||||
# Store mode: project resolved, mode derived as "store", lock hash appended (restore-key drops lock for prefix match)
|
||||
OUT=$(bash "$SCRIPT" "_mageos" "Linux" "8.3.0" "2.2.6" "magento/project-community-edition" "$LOCK_HASH")
|
||||
assert_eq "store: download-key" \
|
||||
"composer | v5.8 | Linux | store | _mageos | 2.2.6 | 8.3.0 | $LOCK_HASH" \
|
||||
"$(field "$OUT" download-key)"
|
||||
assert_eq "store: download-restore-key" \
|
||||
"composer | v5.8 | Linux | store | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" download-restore-key)"
|
||||
assert_eq "store: stamp-key" \
|
||||
"composer | stamp | v5.8 | Linux | store | _mageos | 2.2.6 | 8.3.0 | $LOCK_HASH" \
|
||||
"$(field "$OUT" stamp-key)"
|
||||
|
||||
# Store mode without composer.lock (e.g. stamp=false on a store before `composer install`):
|
||||
# lock_hash is empty, so keys must not carry a trailing " | " with an empty hash slot.
|
||||
OUT=$(bash "$SCRIPT" "_mageos" "Linux" "8.3.0" "2.2.6" "magento/project-community-edition" "")
|
||||
assert_eq "store no-lock: download-key" \
|
||||
"composer | v5.8 | Linux | store | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" download-key)"
|
||||
assert_eq "store no-lock: download-restore-key" \
|
||||
"composer | v5.8 | Linux | store | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" download-restore-key)"
|
||||
assert_eq "store no-lock: stamp-key" \
|
||||
"composer | stamp | v5.8 | Linux | store | _mageos | 2.2.6 | 8.3.0" \
|
||||
"$(field "$OUT" stamp-key)"
|
||||
|
||||
# Custom composer_cache_key, no project resolved
|
||||
OUT=$(bash "$SCRIPT" "custom-v2" "Linux" "8.1.5" "2.4.2" "" "")
|
||||
assert_eq "custom key: download-key" \
|
||||
"composer | v5.8 | Linux | extension | custom-v2 | 2.4.2 | 8.1.5" \
|
||||
"$(field "$OUT" download-key)"
|
||||
assert_eq "custom key: download-restore-key" \
|
||||
"composer | v5.8 | Linux | extension | custom-v2 | 2.4.2 | 8.1.5" \
|
||||
"$(field "$OUT" download-restore-key)"
|
||||
assert_eq "custom key: stamp-key" \
|
||||
"composer | stamp | v5.8 | Linux | extension | custom-v2 | 2.4.2 | 8.1.5" \
|
||||
"$(field "$OUT" stamp-key)"
|
||||
|
||||
# Stamp paths: no excludes — base paths only, with magento2-base always excluded
|
||||
OUT=$(bash "$SCRIPT_STAMP" "/work" "")
|
||||
EXPECTED="/work/vendor/**
|
||||
!/work/vendor/**/
|
||||
!/work/vendor/magento/magento2-base
|
||||
!/work/vendor/magento/magento2-base/**
|
||||
!/work/vendor/mage-os/magento2-base
|
||||
!/work/vendor/mage-os/magento2-base/**"
|
||||
assert_eq "stamp paths: no excludes" "$EXPECTED" "$OUT"
|
||||
|
||||
# Stamp paths: single exclude appended after the always-excluded base entries
|
||||
OUT=$(bash "$SCRIPT_STAMP" "/work" "magento/module-foo")
|
||||
EXPECTED="/work/vendor/**
|
||||
!/work/vendor/**/
|
||||
!/work/vendor/magento/magento2-base
|
||||
!/work/vendor/magento/magento2-base/**
|
||||
!/work/vendor/mage-os/magento2-base
|
||||
!/work/vendor/mage-os/magento2-base/**
|
||||
!/work/vendor/magento/module-foo
|
||||
!/work/vendor/magento/module-foo/**"
|
||||
assert_eq "stamp paths: single exclude" "$EXPECTED" "$OUT"
|
||||
|
||||
# Stamp paths: multiple excludes, with whitespace and blank lines tolerated
|
||||
OUT=$(bash "$SCRIPT_STAMP" "/work" "$(printf 'magento/module-foo\n magento/module-bar \n\nvendor/pkg-baz\n')")
|
||||
EXPECTED="/work/vendor/**
|
||||
!/work/vendor/**/
|
||||
!/work/vendor/magento/magento2-base
|
||||
!/work/vendor/magento/magento2-base/**
|
||||
!/work/vendor/mage-os/magento2-base
|
||||
!/work/vendor/mage-os/magento2-base/**
|
||||
!/work/vendor/magento/module-foo
|
||||
!/work/vendor/magento/module-foo/**
|
||||
!/work/vendor/magento/module-bar
|
||||
!/work/vendor/magento/module-bar/**
|
||||
!/work/vendor/vendor/pkg-baz
|
||||
!/work/vendor/vendor/pkg-baz/**"
|
||||
assert_eq "stamp paths: multiple excludes with whitespace and blank lines" "$EXPECTED" "$OUT"
|
||||
|
||||
echo ""
|
||||
echo "$PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
@@ -1,45 +0,0 @@
|
||||
# Magento 2 Coding Standard Action
|
||||
|
||||
This Github Action automates the enforcement of Magento Coding Standards. It ensures code consistency and quality by checking code against Magento's specific coding guidelines.
|
||||
|
||||
## Inputs
|
||||
|
||||
For detailed descriptions of each input, refer to [action.yml](./action.yml).
|
||||
|
||||
## Why a Baseline?
|
||||
|
||||
Running PHP CodeSniffer (PHPCS) with a baseline is crucial for managing legacy code. It allows you to set a "starting point" for code quality, ignoring existing issues while ensuring no new issues are introduced. This approach is especially useful for large codebases where addressing all existing issues at once is not feasible. The baseline serves as a record of known issues, enabling teams to focus on maintaining and gradually improving code quality in new or modified code.
|
||||
|
||||
## Usage Example
|
||||
|
||||
The following example demonstrates how to set up the action in your workflow:
|
||||
|
||||
Check how this action is used in mage-os [here](https://github.com/mage-os/mageos-magento2/blob/2.4-develop/.github/workflows/coding-standard-baseline.yml).
|
||||
|
||||
```yml
|
||||
name: Coding Standard Baseline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
coding-standard:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: graycoreio/github-actions-magento2/coding-standard-baseline@main
|
||||
with:
|
||||
head_repo: "mage-os/mageos-magento2"
|
||||
head_ref: "main"
|
||||
php_version: "8.2"
|
||||
composer_version: "2"
|
||||
version: "*"
|
||||
severity: "5"
|
||||
warning_severity: "8"
|
||||
error_severity: "8"
|
||||
baseline_version: "*"
|
||||
```
|
||||
@@ -1,151 +0,0 @@
|
||||
name: "M2 Coding Standard"
|
||||
author: "Mage-OS"
|
||||
description: "A Github Action that runs the Magento Coding Standard."
|
||||
|
||||
inputs:
|
||||
php_version:
|
||||
type: string
|
||||
required: true
|
||||
default: "8.2"
|
||||
description: "PHP version used to do the coding standard check (default: 8.2)."
|
||||
|
||||
composer_version:
|
||||
type: string
|
||||
required: true
|
||||
default: "2"
|
||||
description: "The version of composer to use (default: 2)."
|
||||
|
||||
version:
|
||||
type: string
|
||||
required: false
|
||||
default: "*"
|
||||
description: "The version of the coding standard to use (default: latest)."
|
||||
|
||||
severity:
|
||||
type: string
|
||||
required: false
|
||||
default: "5"
|
||||
description: "The minimum severity required to display an error or warning (default: 5)"
|
||||
|
||||
warning_severity:
|
||||
type: string
|
||||
required: false
|
||||
default: "8"
|
||||
description: "The minimum severity required to display a warning (default: 8)."
|
||||
|
||||
error_severity:
|
||||
type: string
|
||||
required: false
|
||||
default: "8"
|
||||
description: "The minimum severity required to display an error (default: 8)."
|
||||
|
||||
baseline_version:
|
||||
type: string
|
||||
required: false
|
||||
default: "*"
|
||||
description: "The version of phpcs baseline to use (default: latest)."
|
||||
|
||||
head_repo:
|
||||
type: string
|
||||
required: true
|
||||
description: "The repository full name of the head branch. E.g.: mage-os/mageos-magento2"
|
||||
|
||||
head_ref:
|
||||
type: string
|
||||
required: true
|
||||
description: "The branch name of the head branch. E.g.: main"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout head
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.head_ref }}
|
||||
repository: ${{ inputs.head_repo }}
|
||||
|
||||
- uses: dorny/paths-filter@v2
|
||||
name: Filter changed files
|
||||
id: filter
|
||||
with:
|
||||
list-files: shell
|
||||
filters: |
|
||||
baseline:
|
||||
- modified: '**/**.{php,phtml,graphqls,less,css,html,xml,js}'
|
||||
phpcs:
|
||||
- added|modified: '**/**.{php,phtml,graphqls,less,css,html,xml,js}'
|
||||
|
||||
- name: Check changed files for PHPcs
|
||||
if: steps.filter.outputs.phpcs == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
echo "One or more files relevant to PHPCS have changed."
|
||||
echo "List all the files that have been added or changed: ${{ steps.filter.outputs.phpcs_files }}"
|
||||
|
||||
- name: Setup PHP
|
||||
if: steps.filter.outputs.phpcs == 'true'
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ inputs.php_version }}
|
||||
tools: composer:v${{ inputs.composer_version }}
|
||||
coverage: none
|
||||
|
||||
- name: Install coding standards
|
||||
if: steps.filter.outputs.phpcs == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
composer create-project --no-plugins --no-dev \
|
||||
magento/magento-coding-standard \
|
||||
magento-coding-standard "${{ github.event.inputs.version || '*' }}"
|
||||
|
||||
- name: Install phpcs baseline
|
||||
if: steps.filter.outputs.phpcs == 'true'
|
||||
working-directory: magento-coding-standard
|
||||
shell: bash
|
||||
run: |
|
||||
composer config --no-plugins allow-plugins.digitalrevolution/php-codesniffer-baseline true
|
||||
composer require --dev "digitalrevolution/php-codesniffer-baseline: ${{ github.event.inputs.baseline_version || '*' }}"
|
||||
|
||||
- name: Checkout base
|
||||
if: steps.filter.outputs.phpcs == 'true'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{github.event.pull_request.base.ref}}
|
||||
repository: ${{github.event.pull_request.base.repo.full_name}}
|
||||
path: base
|
||||
|
||||
- name: Create phpcs.baseline.xml from base
|
||||
shell: bash
|
||||
working-directory: base
|
||||
if: steps.filter.outputs.baseline == 'true'
|
||||
run: |
|
||||
php ${{ github.workspace }}/magento-coding-standard/vendor/bin/phpcs --standard=Magento2 \
|
||||
$([ -n "${{ inputs.severity }}" ] && echo "--severity=${{ inputs.severity }}") \
|
||||
$([ -n "${{ inputs.warning_severity }}" ] && echo "--warning-severity=${{ inputs.warning_severity }}") \
|
||||
$([ -n "${{ inputs.error_severity }}" ] && echo "--error-severity=${{ inputs.error_severity }}") \
|
||||
--report=\\DR\\CodeSnifferBaseline\\Reports\\Baseline --report-file=phpcs.baseline.xml \
|
||||
${{ steps.filter.outputs.baseline_files }} || /bin/true
|
||||
|
||||
- name: Copy baseline to head
|
||||
if: steps.filter.outputs.baseline == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
cp ${{ github.workspace }}/base/phpcs.baseline.xml ${{ github.workspace }}/magento-coding-standard/phpcs.baseline.xml
|
||||
|
||||
# Since we ran phpcs in the base folder, the files in phpcs.baseline.xml contain the base folder in the path.
|
||||
# We need to remove /base/ so that the phpcs can locate the correct files.
|
||||
- name: Remove base dir from phpcs baseline
|
||||
if: steps.filter.outputs.baseline == 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
sed -i "s|/base/|/|" ${{ github.workspace }}/magento-coding-standard/phpcs.baseline.xml
|
||||
|
||||
- name: Execute phpcs on head for changed files
|
||||
shell: bash
|
||||
if: steps.filter.outputs.phpcs == 'true'
|
||||
run: |
|
||||
php ${{ github.workspace }}/magento-coding-standard/vendor/bin/phpcs --standard=Magento2 \
|
||||
$([ -n "${{ inputs.severity }}" ] && echo "--severity=${{ inputs.severity }}") \
|
||||
$([ -n "${{ inputs.warning_severity }}" ] && echo "--warning-severity=${{ inputs.warning_severity }}") \
|
||||
$([ -n "${{ inputs.error_severity }}" ] && echo "--error-severity=${{ inputs.error_severity }}") \
|
||||
${{ steps.filter.outputs.phpcs_files }}
|
||||
@@ -11,6 +11,8 @@ See the [action.yml](./action.yml)
|
||||
|
||||
## Usage
|
||||
|
||||
The caller is responsible for checking out the repository and setting up PHP before calling this action.
|
||||
|
||||
```yml
|
||||
name: Coding Standard
|
||||
|
||||
@@ -26,11 +28,19 @@ jobs:
|
||||
coding-standard:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: graycoreio/github-actions-magento2/coding-standard@main
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: '8.3'
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/coding-standard@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
path: app/code # Optional, defaults to .
|
||||
version: 25 # Optional, will use the latest if omitted.
|
||||
path: app/code # Optional, will be used when event is not a pull request.
|
||||
severity: 8 # Optional, will use phpcs default of 5 if not specified.
|
||||
warning_severity: 4 # Optional, will use severity value if not specified.
|
||||
error_severity: 7 # Optional, will use severity value if not specified.
|
||||
```
|
||||
```
|
||||
+60
-52
@@ -3,35 +3,25 @@ author: "Graycore"
|
||||
description: "A Github Action that runs the Magento Coding Standard."
|
||||
|
||||
inputs:
|
||||
php_version:
|
||||
required: true
|
||||
default: "8.1"
|
||||
description: "PHP version used to do the coding standard check."
|
||||
|
||||
composer_version:
|
||||
required: true
|
||||
default: "2"
|
||||
description: "The version of composer to use."
|
||||
|
||||
path:
|
||||
required: true
|
||||
default: 'app/code'
|
||||
description: "The directory (relative to the project root) in which the coding standard will be checked. Used when the event is not a pull request."
|
||||
default: '.'
|
||||
description: "The directory containing the code to check."
|
||||
|
||||
version:
|
||||
required: false
|
||||
description: "The version of the coding standard to use. If not provided, will use the latest version."
|
||||
|
||||
|
||||
severity:
|
||||
required: false
|
||||
default: ""
|
||||
description: "The minimum severity required to display an error or warning (default: 5)"
|
||||
|
||||
|
||||
warning_severity:
|
||||
required: false
|
||||
default: ""
|
||||
description: "The minimum severity required to display a warning"
|
||||
|
||||
|
||||
error_severity:
|
||||
required: false
|
||||
default: ""
|
||||
@@ -42,72 +32,90 @@ inputs:
|
||||
default: 'false'
|
||||
required: false
|
||||
|
||||
composer_auth:
|
||||
required: false
|
||||
default: ""
|
||||
description: "Composer authentication credentials (contents of auth.json as a JSON string)"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
path: project
|
||||
|
||||
- name: Create Standard Directory
|
||||
- name: Check if Coding Standard is already installed
|
||||
id: check-installed
|
||||
shell: bash
|
||||
run: mkdir standard
|
||||
|
||||
- name: Set PHP Version
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ inputs.php_version }}
|
||||
tools: composer:v${{ inputs.composer_version }}
|
||||
coverage: none
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: |
|
||||
if [ -d "vendor/magento/magento-coding-standard" ] || [ -d "vendor/mage-os/magento-coding-standard" ]; then
|
||||
echo "installed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "installed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Get Composer Version
|
||||
uses: graycoreio/github-actions-magento2/get-composer-version@main
|
||||
id: get-composer-version
|
||||
if: steps.check-installed.outputs.installed != 'true'
|
||||
|
||||
- name: Check if allow-plugins option is available for this version of composer
|
||||
uses: graycoreio/github-actions-magento2/semver-compare@main
|
||||
id: is-allow-plugins-available
|
||||
if: steps.check-installed.outputs.installed != 'true'
|
||||
with:
|
||||
version: 2.2
|
||||
compare_against: ${{ steps.get-composer-version.outputs.version }}
|
||||
id: is-allow-plugins-available
|
||||
|
||||
- name: Enable dealerdirect/phpcodesniffer-composer-installer plugin
|
||||
shell: bash
|
||||
working-directory: standard
|
||||
run: composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true --global
|
||||
if: steps.is-allow-plugins-available.outputs.result < 1
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: composer config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true --global
|
||||
if: steps.check-installed.outputs.installed != 'true' && steps.is-allow-plugins-available.outputs.result < 1
|
||||
|
||||
- name: Install Coding Standard
|
||||
shell: bash
|
||||
working-directory: standard
|
||||
run: composer require "magento/magento-coding-standard:${{ inputs.version || '*' }}"
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: composer require "magento/magento-coding-standard:${{ inputs.version || '*' }}" "magento/php-compatibility-fork"
|
||||
if: steps.check-installed.outputs.installed != 'true'
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ inputs.composer_auth }}
|
||||
|
||||
- name: Register Coding Standard
|
||||
shell: bash
|
||||
working-directory: standard
|
||||
run: vendor/bin/phpcs --config-set installed_paths ${{ github.workspace }}/standard/vendor/magento/magento-coding-standard,${{ github.workspace }}/standard/vendor/magento/php-compatibility-fork
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: |
|
||||
if [ -d vendor/magento/magento-coding-standard ]; then
|
||||
CODING_STANDARD_VENDOR=magento
|
||||
elif [ -d vendor/mage-os/magento-coding-standard ]; then
|
||||
CODING_STANDARD_VENDOR=mage-os
|
||||
else
|
||||
echo "No magento-coding-standard directory found under vendor/magento or vendor/mage-os."
|
||||
echo "Trusting dealerdirect/phpcodesniffer-composer-installer to have registered installed_paths."
|
||||
exit 0
|
||||
fi
|
||||
vendor/bin/phpcs --config-set installed_paths \
|
||||
"vendor/${CODING_STANDARD_VENDOR}/magento-coding-standard,vendor/${CODING_STANDARD_VENDOR}/php-compatibility-fork"
|
||||
if: steps.check-installed.outputs.installed != 'true'
|
||||
|
||||
- name: Set ignore warnings flag
|
||||
shell: bash
|
||||
working-directory: standard
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: vendor/bin/phpcs --config-set ignore_warnings_on_exit 1
|
||||
if: inputs.ignore_warnings == 'true'
|
||||
|
||||
- name: Get Changed Files
|
||||
shell: bash
|
||||
working-directory: project
|
||||
id: changed-files
|
||||
run: echo "files=$(git diff --name-only --diff-filter=ACMRT ${{ github.event.pull_request.base.sha }} ${{ github.sha }} | xargs)" >> $GITHUB_OUTPUT
|
||||
if: github.event_name == 'pull_request'
|
||||
|
||||
- name: Coding Standard Check
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.path }}
|
||||
run: |
|
||||
../standard/vendor/bin/phpcs --standard=Magento2 \
|
||||
$([ -n "${{ inputs.severity }}" ] && echo "--severity=${{ inputs.severity }}") \
|
||||
$([ -n "${{ inputs.warning_severity }}" ] && echo "--warning-severity=${{ inputs.warning_severity }}") \
|
||||
$([ -n "${{ inputs.error_severity }}" ] && echo "--error-severity=${{ inputs.error_severity }}") \
|
||||
${{ github.event_name == 'pull_request' && steps.changed-files.outputs.files || inputs.path }}
|
||||
working-directory: project
|
||||
FLAGS=()
|
||||
[ -n "${{ inputs.severity }}" ] && FLAGS+=(--severity=${{ inputs.severity }}) || true
|
||||
[ -n "${{ inputs.warning_severity }}" ] && FLAGS+=(--warning-severity=${{ inputs.warning_severity }}) || true
|
||||
[ -n "${{ inputs.error_severity }}" ] && FLAGS+=(--error-severity=${{ inputs.error_severity }}) || true
|
||||
|
||||
if [ -f .phpcs.xml ] || [ -f phpcs.xml ] || [ -f .phpcs.xml.dist ] || [ -f phpcs.xml.dist ]; then
|
||||
vendor/bin/phpcs "${FLAGS[@]}"
|
||||
else
|
||||
vendor/bin/phpcs --standard=Magento2 --ignore=*vendor/* "${FLAGS[@]}" .
|
||||
fi
|
||||
|
||||
branding:
|
||||
icon: "code"
|
||||
color: "green"
|
||||
@@ -0,0 +1,71 @@
|
||||
# Configure Service Nginx
|
||||
|
||||
A GitHub Action that pushes a Magento-aware nginx configuration into an **already-running nginx service container**, reloads it, and waits for the container's healthcheck to pass.
|
||||
|
||||
The action does **not** start nginx. It assumes the calling workflow declared nginx as a `services:` container (typically alongside `php-fpm`, and other mandatory Magento services).
|
||||
|
||||
The shipped `default.conf` is a thin outer wrapper that defines a `fastcgi_backend` upstream pointing at `php-fpm:9000`, sets `$MAGE_ROOT`, and includes Magento's own `nginx.conf.sample` from your own Magento install. All real routing rules come from Magento's bundled file.
|
||||
|
||||
## When to use this
|
||||
|
||||
Use this action when you have a workflow that:
|
||||
|
||||
1. Boots nginx as `services:` containers with the workspace bind-mounted at `/var/www/html`, and
|
||||
2. Wants those containers to actually serve a Magento store you've already installed into the workspace (e.g. for end-to-end smoke tests, integration tests, or any HTTP-driven check).
|
||||
|
||||
You do **not** need this action if:
|
||||
|
||||
- You're not running nginx at all (unit tests, coding standards, static analysis).
|
||||
- nginx is started by something other than a GitHub Actions `services:` block
|
||||
- You've already configured nginx some other way and don't need a Magento-ready outer config.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- An nginx service container is running on the same Docker host as the runner, with an image matching the `image` input.
|
||||
- A `php-fpm` container, the included `default.conf` will set up a fast-cgi backend to `php-fpm:9000`.
|
||||
- The runner's workspace (`$GITHUB_WORKSPACE`) is bind-mounted into the nginx container at `/var/www/html`.
|
||||
- A Magento install exists at `${{ inputs.magento_path }}` relative to the workspace, with `nginx.conf.sample` present (it ships with Magento by default after `composer install`).
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Required | Default | Description |
|
||||
| ------------------------ | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `container_id` | Yes | — | The ID of the running nginx service container. Pass `${{ job.services.nginx.id }}` (replace `nginx` with whatever you named the service). |
|
||||
| `magento_path` | No | `.` | Path to the Magento store, relative to the GitHub workspace. Combined with the `/var/www/html` mount prefix to compute the in-container `MAGE_ROOT`. |
|
||||
| `health_timeout_seconds` | No | `10` | How long to wait for nginx to report `healthy` after the config is pushed and the container restarts. |
|
||||
|
||||
## Usage
|
||||
|
||||
```yml
|
||||
jobs:
|
||||
smoke-test:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
## There are other service requirements for Magento, but this is just for the explanation of this service
|
||||
nginx:
|
||||
image: nginx:1.27-alpine
|
||||
ports: ["80:80"]
|
||||
volumes:
|
||||
- ${{ github.workspace }}:/var/www/html
|
||||
options: --health-cmd "nginx -t" --health-interval=10s --health-retries=3
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/setup-magento@main
|
||||
id: setup-magento
|
||||
with:
|
||||
mode: store
|
||||
- run: composer install
|
||||
working-directory: ${{ steps.setup-magento.outputs.path }}
|
||||
- uses: graycoreio/github-actions-magento2/setup-install@main
|
||||
with:
|
||||
services: ${{ toJSON(matrix.services) }}
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
container_id: ${{ job.services['php-fpm'].id }}
|
||||
- uses: graycoreio/github-actions-magento2/configure-service-nginx@main
|
||||
with:
|
||||
container_id: ${{ job.services.nginx.id }}
|
||||
magento_path: ${{ inputs.path }}
|
||||
- uses: graycoreio/github-actions-magento2/smoke-test@main
|
||||
with:
|
||||
kind: page
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
name: "Configure nginx service container"
|
||||
author: "Graycore"
|
||||
description: "Pushes a Magento-aware nginx config into an already-running nginx service container, restarts it, and waits for the container healthcheck to pass."
|
||||
|
||||
inputs:
|
||||
container_id:
|
||||
description: "The ID of the running nginx service container. Pass the value of `job.services.nginx.id` (replace `nginx` with whatever you named the service in `services:`)."
|
||||
required: true
|
||||
magento_path:
|
||||
description: "Path to the Magento store, relative to the GitHub workspace. The workspace is mounted at /var/www/html in both the nginx and php-fpm service containers, so this is combined with that prefix to compute MAGE_ROOT."
|
||||
required: false
|
||||
default: "."
|
||||
health_timeout_seconds:
|
||||
description: "How long to wait for nginx to become healthy after the config is pushed and the container is restarted."
|
||||
required: false
|
||||
default: "10"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Push nginx config
|
||||
shell: bash
|
||||
env:
|
||||
NGINX_CID: ${{ inputs.container_id }}
|
||||
ACTION_PATH: ${{ github.action_path }}
|
||||
MAGENTO_PATH: ${{ inputs.magento_path }}
|
||||
run: |
|
||||
case "$MAGENTO_PATH" in
|
||||
""|".") MAGE_ROOT="/var/www/html" ;;
|
||||
/*) MAGE_ROOT="$MAGENTO_PATH" ;;
|
||||
*) MAGE_ROOT="/var/www/html/$MAGENTO_PATH" ;;
|
||||
esac
|
||||
MAGE_ROOT="${MAGE_ROOT%/}"
|
||||
|
||||
sed "s|__MAGE_ROOT__|$MAGE_ROOT|g" "$ACTION_PATH/conf.d/default.conf" > /tmp/default.conf
|
||||
|
||||
docker cp /tmp/default.conf "$NGINX_CID:/etc/nginx/conf.d/default.conf"
|
||||
|
||||
echo "--- default.conf in container ---"
|
||||
docker exec "$NGINX_CID" cat /etc/nginx/conf.d/default.conf
|
||||
docker exec "$NGINX_CID" nginx -t
|
||||
|
||||
- name: Restart nginx and wait for healthy
|
||||
shell: bash
|
||||
env:
|
||||
NGINX_CID: ${{ inputs.container_id }}
|
||||
TIMEOUT: ${{ inputs.health_timeout_seconds }}
|
||||
run: |
|
||||
docker restart "$NGINX_CID"
|
||||
deadline=$(( $(date +%s) + TIMEOUT ))
|
||||
last=""
|
||||
while [ "$(date +%s)" -lt "$deadline" ]; do
|
||||
last=$(docker inspect --format '{{.State.Health.Status}}' "$NGINX_CID" 2>/dev/null || echo "")
|
||||
running=$(docker inspect --format '{{.State.Running}}' "$NGINX_CID" 2>/dev/null || echo "")
|
||||
echo "running=$running health=$last"
|
||||
if [ "$last" = "healthy" ]; then
|
||||
exit 0
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
echo "nginx did not reach healthy state within ${TIMEOUT}s (last=$last)"
|
||||
docker logs "$NGINX_CID" 2>&1 | tail -80 || true
|
||||
exit 1
|
||||
|
||||
branding:
|
||||
icon: "code"
|
||||
color: "green"
|
||||
@@ -0,0 +1,10 @@
|
||||
upstream fastcgi_backend {
|
||||
server php-fpm:9000;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name _;
|
||||
set $MAGE_ROOT __MAGE_ROOT__;
|
||||
include __MAGE_ROOT__/nginx[.]conf*;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# What belongs in a composite action
|
||||
|
||||
A composite action should do one thing. The guiding test: **can a caller reasonably want to skip part of what this action does, independently of the rest?** If yes, those parts should be separate actions that the caller composes themselves.
|
||||
|
||||
## Good fits for a composite action
|
||||
|
||||
**A single tool installation paired with its execution.** Install the tool, run it, done. `coding-standard` installs PHPCS and runs it. `fix-magento-install` applies a known set of patches. The install and the run are not independently useful — splitting them would add complexity with no benefit.
|
||||
|
||||
**A utility that extracts and exposes a single value.** `get-composer-version`, `get-magento-version`, and `semver-compare` each run one or two commands and write an output. These exist because their output is needed inline by the next step in the same job. That is the right scope for a composite action.
|
||||
|
||||
**A setup operation with a well-defined end state.** `cache-magento` leaves the Composer cache populated. `setup-magento` leaves a Magento project at a known path. The caller gets a clear postcondition and nothing else.
|
||||
|
||||
## Signs an action is too broad
|
||||
|
||||
**It bundles independent setup concerns with execution.** Imagine a `unit-test` action that sets up PHP, installs Composer dependencies, and then runs the test command. These three things can each be wanted or skipped independently. A caller whose job already has PHP set up cannot avoid step 1. A caller that wants to run tests against already-installed dependencies cannot avoid step 2.
|
||||
|
||||
The right scope is just the execution step:
|
||||
|
||||
```yaml
|
||||
inputs:
|
||||
test_command:
|
||||
required: true
|
||||
default: composer run test
|
||||
source_folder:
|
||||
required: true
|
||||
default: .
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- run: ${{ inputs.test_command }}
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.source_folder }}
|
||||
```
|
||||
|
||||
The caller is then responsible for composing `setup-php`, `cache-magento`, and `composer install` before calling it — each of which is already a separate action in this repo.
|
||||
|
||||
**It reimplements logic that already exists in another action.** If a new action rolls its own Composer caching inline rather than calling `cache-magento`, that creates two different cache key strategies in the same repo and makes it harder to update caching behavior consistently.
|
||||
|
||||
**The name describes a pipeline, not a step.** Names like "install and test" or "build and deploy" are warning signs. A good action name describes what state it produces or what it checks — not a sequence of operations.
|
||||
@@ -4,7 +4,7 @@ A Github Workflow that runs various kinds of quality checks for a Magento Extens
|
||||
|
||||
## Inputs
|
||||
|
||||
See the [check-extension.yaml](./check-extension.yaml)
|
||||
See the [check-extension.yaml](../../.github/workflows/check-extension.yaml)
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------------------- |
|
||||
@@ -18,6 +18,23 @@ See the [check-extension.yaml](./check-extension.yaml)
|
||||
|
||||
The Magento matrix format outlined by the [supported versions action.](https://github.com/graycoreio/github-actions-magento2/tree/main/supported-version/supported.json)
|
||||
|
||||
## Configuration
|
||||
|
||||
Each check can be toggled on/off through an optional `.github/check-extension.json` file in the repo that calls this workflow.
|
||||
|
||||
You can learn more about this file here in the [`resolve-check-config` action.](../../resolve-check-config/README.md):
|
||||
|
||||
Reference the published JSON Schema with `$schema` to get autocompletion and inline validation in editors that support it — see [`check-extension.schema.json`](../../resolve-check-config/check-extension.schema.json):
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/graycoreio/github-actions-magento2/main/resolve-check-config/check-extension.schema.json",
|
||||
"jobs": {
|
||||
"integration_test": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```yml
|
||||
@@ -37,13 +54,13 @@ jobs:
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@main
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@v8.5.0 # x-release-please-version
|
||||
id: supported-version
|
||||
- run: echo ${{ steps.supported-version.outputs.matrix }}
|
||||
check-extension:
|
||||
needs: compute_matrix
|
||||
uses: graycoreio/github-actions-magento2/.github/workflows/check-extension.yaml@main
|
||||
uses: graycoreio/github-actions-magento2/.github/workflows/check-extension.yaml@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
matrix: ${{ needs.compute_matrix.outputs.matrix }}
|
||||
```
|
||||
@@ -0,0 +1,76 @@
|
||||
# MageCheck Store
|
||||
|
||||
A Github Workflow that runs various kinds of quality checks for a Magento Store.
|
||||
|
||||
Unlike [MageCheck Extension](./check-extension.md), this workflow automatically detects the Magento version from your store's `composer.lock` — no matrix computation required in the calling workflow.
|
||||
|
||||
## Inputs
|
||||
|
||||
See the [check-store.yaml](../../.github/workflows/check-store.yaml)
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
| ------------------- | -------------------------------------------------------------------------------------- | -------- | --------- |
|
||||
| path | The folder of the Magento store that you are testing | false | . |
|
||||
| composer_cache_key | A key to version the composer cache. Can be incremented if you need to bust the cache. | false | \_mageos |
|
||||
| store_artifact_name | If provided, download store files from this artifact instead of using actions/checkout | false | "" |
|
||||
|
||||
## Secrets
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- |
|
||||
| composer_auth | Your composer credentials (typically a stringified json object of the contents of your auth.json) | false | NULL |
|
||||
|
||||
## Checks Run
|
||||
|
||||
- **Unit Tests** — runs PHPUnit against custom code in `app/code`. Skipped automatically if no test files are found.
|
||||
- **Coding Standard** — runs the Magento Coding Standard against `app/code`. Uses your `phpcs.xml` (or `.phpcs.xml`, `phpcs.xml.dist`, `.phpcs.xml.dist`) if one exists, otherwise a sensible default is generated.
|
||||
- **Smoke Test** — boots your store against the supported-version service set (mysql, search, queue, cache, nginx, php-fpm) and runs the smoke probes against it.
|
||||
|
||||
## Configuration
|
||||
|
||||
Each check can be toggled on/off through an optional `.github/check-store.json` file in the repo that calls this workflow.
|
||||
|
||||
You can learn more about this file here in the [`resolve-check-config` action.](../../resolve-check-config/README.md):
|
||||
|
||||
Reference the published JSON Schema with `$schema` to get autocompletion and inline validation in editors that support it — see [`check-store.schema.json`](../../resolve-check-config/check-store.schema.json):
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/graycoreio/github-actions-magento2/main/resolve-check-config/check-store.schema.json",
|
||||
"jobs": {
|
||||
"coding-standard": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```yml
|
||||
name: Check Store
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
check-store:
|
||||
uses: graycoreio/github-actions-magento2/.github/workflows/check-store.yaml@v8.5.0 # x-release-please-version
|
||||
secrets:
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
```
|
||||
|
||||
### Usage with a store artifact
|
||||
|
||||
If your pipeline builds or prepares the store in a prior job and uploads it as an artifact, you can pass the artifact name instead of relying on `actions/checkout`:
|
||||
|
||||
```yml
|
||||
jobs:
|
||||
check-store:
|
||||
uses: graycoreio/github-actions-magento2/.github/workflows/check-store.yaml@v8.5.0 # x-release-please-version
|
||||
secrets:
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
```
|
||||
@@ -1,16 +1,19 @@
|
||||
# Integration Tests for a Magento Package
|
||||
|
||||
> **Deprecated** — use [MageCheck Extension](./check-extension.md) instead. Scheduled for removal in v10.
|
||||
|
||||
A Github Workflow that runs the Integration Tests of a Magento Package
|
||||
|
||||
## Inputs
|
||||
|
||||
See the [integration.yaml](./integration.yaml)
|
||||
See the [integration.yaml](../../.github/workflows/integration.yaml)
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------------- |
|
||||
| matrix | JSON string of [version matrix for Magento](./#matrix-format) | true | NULL |
|
||||
| matrix | JSON string of [version matrix for Magento](./#matrix-format). Must include a `services` key (pass `include_services: true` to the supported-version action). | true | NULL |
|
||||
| fail-fast | Same as Github's [fail-fast](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategyfail-fast) | false | true |
|
||||
| package_name | The name of the package | true | NULL |
|
||||
| use_local_source | Whether or not you want to test your local package or not. | false | true |
|
||||
| source_folder | The source folder of the package | false | $GITHUB_WORKSPACE |
|
||||
| magento_directory | The folder where Magento will be installed | false | ../magento2 |
|
||||
| magento_repository | Where to install Magento from | false | https://mirror.mage-os.org/ |
|
||||
@@ -46,13 +49,14 @@ jobs:
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@main
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
include_services: true
|
||||
id: supported-version
|
||||
- run: echo ${{ steps.supported-version.outputs.matrix }}
|
||||
integration-workflow:
|
||||
needs: compute_matrix
|
||||
uses: graycoreio/github-actions-magento2/.github/workflows/integration.yaml@main
|
||||
uses: graycoreio/github-actions-magento2/.github/workflows/integration.yaml@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
package_name: my-vendor/package
|
||||
matrix: ${{ needs.compute_matrix.outputs.matrix }}
|
||||
@@ -25,8 +25,8 @@ jobs:
|
||||
fix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: graycoreio/github-actions-magento2/fix-magento-install@main
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/fix-magento-install@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
magento_directory: path/to/magento
|
||||
```
|
||||
|
||||
@@ -14,7 +14,7 @@ runs:
|
||||
with:
|
||||
working-directory: ${{ inputs.magento_directory }}
|
||||
|
||||
- run: echo "::set-output name=version::$(composer --version | awk '{print $3}')"
|
||||
- run: echo "version=$(composer --version | awk '{print $3}')" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
name: Compute Composer Version
|
||||
id: init-magento-get-composer-version
|
||||
|
||||
@@ -24,8 +24,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: A job to compute an installed Composer version.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: graycoreio/github-actions-magento2/get-composer-version@main
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/get-composer-version@v8.5.0 # x-release-please-version
|
||||
id: get-composer-version
|
||||
- run: echo version ${{ steps.get-composer-version.outputs.version }}
|
||||
shell: bash
|
||||
|
||||
@@ -24,8 +24,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: A job to compute an installed Magento version.
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: graycoreio/github-actions-magento2/get-magento-version@main
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/get-magento-version@v8.5.0 # x-release-please-version
|
||||
id: get-magento-version
|
||||
- run: echo version ${{ steps.get-magento-version.outputs.version }}
|
||||
shell: bash
|
||||
|
||||
@@ -2,29 +2,30 @@ name: "Get Magento Version"
|
||||
author: "Graycore"
|
||||
description: " A Github Action that determines the currently installed version of Magento"
|
||||
|
||||
inputs:
|
||||
working-directory:
|
||||
inputs:
|
||||
working-directory:
|
||||
default: $GITHUB_WORKSPACE
|
||||
description: "The current working directory of the action"
|
||||
required: false
|
||||
|
||||
outputs:
|
||||
version: # id of output
|
||||
description: 'The determined version of Magento'
|
||||
version:
|
||||
description: 'The resolved Magento version (e.g. 2.4.6-p14)'
|
||||
value: ${{ steps.get-magento-version.outputs.version }}
|
||||
project:
|
||||
description: 'The Magento project package name (e.g. magento/project-community-edition)'
|
||||
value: ${{ steps.get-magento-version.outputs.project }}
|
||||
supported_version_project:
|
||||
description: 'The `project` value to pass to the supported-version action (e.g. `magento-open-source`, `mage-os`, `mage-os-minimal`). Empty when no Magento project is detected.'
|
||||
value: ${{ steps.get-magento-version.outputs.supported_version_project }}
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- run: |
|
||||
echo "version=$(cat composer.json | jq '.require
|
||||
| with_entries( select(.key == "magento/product-community-edition" or .key == "magento/product-enterprise-edition") )
|
||||
| to_entries
|
||||
| .[0].value')" >> $GITHUB_OUTPUT
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.working-directory }}
|
||||
name: Compute Installed Magento version
|
||||
- name: Compute Installed Magento version
|
||||
id: get-magento-version
|
||||
shell: bash
|
||||
run: bash "${{ github.action_path }}/get-magento-version.sh" "${{ inputs.working-directory }}" >> $GITHUB_OUTPUT
|
||||
|
||||
branding:
|
||||
icon: "code"
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "magento/product-enterprise-edition",
|
||||
"version": "2.4.7-p1"
|
||||
}
|
||||
],
|
||||
"packages-dev": []
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "vendor/module",
|
||||
"type": "magento2-module",
|
||||
"require": {}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "mage-os/product-minimal-edition",
|
||||
"version": "3.0.0"
|
||||
}
|
||||
],
|
||||
"packages-dev": []
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "mage-os/product-community-edition",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
],
|
||||
"packages-dev": []
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"require": {
|
||||
"magento/product-community-edition": "2.4.6-p1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "magento/product-community-edition",
|
||||
"version": "2.4.7"
|
||||
}
|
||||
],
|
||||
"packages-dev": []
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"packages": [
|
||||
{
|
||||
"name": "magento/product-community-edition",
|
||||
"version": "v2.4.6"
|
||||
}
|
||||
],
|
||||
"packages-dev": []
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#!/usr/bin/env bash
|
||||
set -uo pipefail
|
||||
|
||||
WORKING_DIR="${1:-.}"
|
||||
PATTERN="magento/product-(community|enterprise)-edition|mage-os/product-(community|minimal)-edition"
|
||||
|
||||
cd "$WORKING_DIR"
|
||||
|
||||
if [ -f composer.lock ]; then
|
||||
RESULT=$(jq -r --arg p "$PATTERN" '.packages[] | select(.name | test($p)) | "\(.name) \(.version)"' composer.lock | head -1)
|
||||
elif [ -f composer.json ]; then
|
||||
RESULT=$(jq -r --arg p "$PATTERN" '.require | to_entries[] | select(.key | test($p)) | "\(.key) \(.value)"' composer.json | head -1)
|
||||
fi
|
||||
|
||||
PRODUCT=$(echo "${RESULT:-}" | awk '{print $1}')
|
||||
VERSION=$(echo "${RESULT:-}" | awk '{print $2}' | sed 's/^v//')
|
||||
PROJECT=$(echo "$PRODUCT" | sed 's/product-/project-/')
|
||||
|
||||
case "$PROJECT" in
|
||||
magento/*) SUPPORTED_VERSION_PROJECT="magento-open-source" ;;
|
||||
mage-os/project-community-edition) SUPPORTED_VERSION_PROJECT="mage-os" ;;
|
||||
mage-os/project-minimal-edition) SUPPORTED_VERSION_PROJECT="mage-os-minimal" ;;
|
||||
*) SUPPORTED_VERSION_PROJECT="" ;;
|
||||
esac
|
||||
|
||||
echo "version=\"$VERSION\""
|
||||
echo "project=$PROJECT"
|
||||
echo "supported_version_project=$SUPPORTED_VERSION_PROJECT"
|
||||
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SCRIPT="$SCRIPT_DIR/get-magento-version.sh"
|
||||
FIXTURES="$SCRIPT_DIR/fixtures"
|
||||
PASS=0
|
||||
FAIL=0
|
||||
|
||||
assert_eq() {
|
||||
local label="$1" expected="$2" actual="$3"
|
||||
if [ "$expected" = "$actual" ]; then
|
||||
echo "PASS: $label"
|
||||
PASS=$((PASS + 1))
|
||||
else
|
||||
echo "FAIL: $label"
|
||||
echo " expected: $expected"
|
||||
echo " actual: $actual"
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
field() {
|
||||
echo "$1" | grep "^${2}=" | cut -d= -f2-
|
||||
}
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/store-lock")
|
||||
assert_eq "store lock: version" '"2.4.7"' "$(field "$OUT" version)"
|
||||
assert_eq "store lock: project" "magento/project-community-edition" "$(field "$OUT" project)"
|
||||
assert_eq "store lock: supported_version_project" "magento-open-source" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/store-v-prefix")
|
||||
assert_eq "store v-prefix: version" '"2.4.6"' "$(field "$OUT" version)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/enterprise")
|
||||
assert_eq "enterprise: version" '"2.4.7-p1"' "$(field "$OUT" version)"
|
||||
assert_eq "enterprise: project" "magento/project-enterprise-edition" "$(field "$OUT" project)"
|
||||
assert_eq "enterprise: supported_version_project" "magento-open-source" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/mage-os")
|
||||
assert_eq "mage-os: version" '"1.0.0"' "$(field "$OUT" version)"
|
||||
assert_eq "mage-os: project" "mage-os/project-community-edition" "$(field "$OUT" project)"
|
||||
assert_eq "mage-os: supported_version_project" "mage-os" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/mage-os-minimal")
|
||||
assert_eq "mage-os-minimal: version" '"3.0.0"' "$(field "$OUT" version)"
|
||||
assert_eq "mage-os-minimal: project" "mage-os/project-minimal-edition" "$(field "$OUT" project)"
|
||||
assert_eq "mage-os-minimal: supported_version_project" "mage-os-minimal" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/store-json")
|
||||
assert_eq "store json: version" '"2.4.6-p1"' "$(field "$OUT" version)"
|
||||
assert_eq "store json: project" "magento/project-community-edition" "$(field "$OUT" project)"
|
||||
assert_eq "store json: supported_version_project" "magento-open-source" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/extension")
|
||||
assert_eq "extension: version" '""' "$(field "$OUT" version)"
|
||||
assert_eq "extension: project" "" "$(field "$OUT" project)"
|
||||
assert_eq "extension: supported_version_project" "" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
OUT=$(bash "$SCRIPT" "$FIXTURES/empty")
|
||||
assert_eq "empty dir: version" '""' "$(field "$OUT" version)"
|
||||
assert_eq "empty dir: project" "" "$(field "$OUT" project)"
|
||||
assert_eq "empty dir: supported_version_project" "" "$(field "$OUT" supported_version_project)"
|
||||
|
||||
echo ""
|
||||
echo "$PASS passed, $FAIL failed"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
@@ -1,48 +0,0 @@
|
||||
# Magento 2 Package Installation Test Action
|
||||
|
||||
A Github Action that tests the installability of a Magento Package
|
||||
|
||||
## Inputs
|
||||
|
||||
See the [action.yml](./action.yml)
|
||||
|
||||
## Usage
|
||||
|
||||
```yml
|
||||
name: Installation Test
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
compute_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@main
|
||||
id: supported-version
|
||||
- run: echo ${{ steps.supported-version.outputs.matrix }}
|
||||
|
||||
install-test:
|
||||
needs: compute_matrix
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: graycoreio/github-actions-magento2/installation-test@main
|
||||
with:
|
||||
composer_version: ${{ matrix.composer }}
|
||||
php_version: ${{ matrix.php }}
|
||||
magento_version: ${{ matrix.magento }}
|
||||
composer_auth: ${{ secrets.COMPOSER_AUTH }}
|
||||
package_name: vendor/package
|
||||
source_folder: $GITHUB_WORKSPACE
|
||||
```
|
||||
@@ -1,122 +0,0 @@
|
||||
name: "Installation Test"
|
||||
author: "Graycore"
|
||||
description: " A Github Action that tests the installability of a Magento Package"
|
||||
|
||||
inputs:
|
||||
php_version:
|
||||
required: true
|
||||
default: "8.1"
|
||||
description: "PHP Version to use"
|
||||
|
||||
cache_key:
|
||||
required: true
|
||||
default: "2"
|
||||
description: "The cache key used to hold Composer Packages"
|
||||
|
||||
composer_version:
|
||||
required: true
|
||||
default: "2"
|
||||
description: "The version of composer to use"
|
||||
|
||||
use_local_source:
|
||||
required: false
|
||||
default: "true"
|
||||
description: "Whether or not you want to test your local package or not."
|
||||
|
||||
source_folder:
|
||||
required: true
|
||||
default: $GITHUB_WORKSPACE
|
||||
description: "The source folder of the package"
|
||||
|
||||
package_name:
|
||||
required: true
|
||||
description: "The name of the package"
|
||||
|
||||
magento_directory:
|
||||
required: true
|
||||
default: "../magento2"
|
||||
description: "The folder where Magento will be installed"
|
||||
|
||||
magento_version:
|
||||
required: true
|
||||
default: "magento/project-community-edition"
|
||||
description: "The version of Magento to test against"
|
||||
|
||||
magento_repository:
|
||||
required: true
|
||||
default: "https://mirror.mage-os.org/"
|
||||
description: "Where to install Magento from"
|
||||
|
||||
composer_cache_key:
|
||||
required: false
|
||||
default: ''
|
||||
description: A key to version the composer cache. Can be incremented if you need to bust the cache.
|
||||
|
||||
composer_auth:
|
||||
required: false
|
||||
description: "Composer Authentication Credentials"
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Set PHP Version
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ inputs.php_version }}
|
||||
|
||||
- run: composer self-update ${{ inputs.composer_version }}
|
||||
name: Pin to Composer Version ${{ inputs.composer_version }}
|
||||
if: contains(inputs.composer_version, '.') == true
|
||||
shell: bash
|
||||
|
||||
- run: composer self-update --${{ inputs.composer_version }}
|
||||
name: Pin to Composer Version ${{ inputs.composer_version }} (Range)
|
||||
if: contains(inputs.composer_version, '.') == false
|
||||
shell: bash
|
||||
|
||||
- run: composer create-project --repository-url="${{ inputs.magento_repository }}" "${{ inputs.magento_version }}" ${{ inputs.magento_directory }} --no-install
|
||||
shell: bash
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ inputs.composer_auth }}
|
||||
name: Create Magento ${{ inputs.magento_version }} Project
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.magento_directory }}
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
|
||||
- name: "Cache Composer Packages"
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: "composer | v5 | ${{ inputs.composer_cache_key }} | ${{ hashFiles('composer.lock') }} | ${{ runner.os }} | ${{ inputs.composer_version }} | ${{ inputs.php_version }} | ${{ inputs.magento_version }}"
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
|
||||
- run: composer config repositories.local path ${{ inputs.source_folder }}
|
||||
name: Add Github Repo for Testing
|
||||
working-directory: ${{ inputs.magento_directory }}
|
||||
shell: bash
|
||||
if: ${{ inputs.use_local_source == 'true' }}
|
||||
|
||||
- run: |
|
||||
composer config --no-interaction allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
|
||||
composer config --no-interaction allow-plugins.laminas/laminas-dependency-plugin true
|
||||
composer config --no-interaction allow-plugins.magento/* true
|
||||
name: Fixup Composer Plugins
|
||||
shell: bash
|
||||
working-directory: ${{ inputs.magento_directory }}
|
||||
if: ${{ !startsWith(inputs.composer_version, '1') }}
|
||||
|
||||
- run: composer require ${{ inputs.package_name }} "@dev" --no-update && composer install
|
||||
name: Require and attempt install
|
||||
working-directory: ${{ inputs.magento_directory }}
|
||||
shell: bash
|
||||
env:
|
||||
COMPOSER_CACHE_DIR: ${{ steps.composer-cache.outputs.dir }}
|
||||
COMPOSER_AUTH: ${{ inputs.composer_auth }}
|
||||
|
||||
branding:
|
||||
icon: "code"
|
||||
color: "green"
|
||||
Generated
+23
-7
@@ -1,15 +1,16 @@
|
||||
{
|
||||
"name": "@graycoreio/github-actions-magento2",
|
||||
"version": "4.0.0",
|
||||
"version": "8.5.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@graycoreio/github-actions-magento2",
|
||||
"version": "4.0.0",
|
||||
"version": "8.5.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1"
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.14",
|
||||
@@ -33,7 +34,7 @@
|
||||
"@actions/http-client": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"node_modules/@actions/core/node_modules/@actions/exec": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
|
||||
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
|
||||
@@ -42,6 +43,21 @@
|
||||
"@actions/io": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/core/node_modules/@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@actions/exec": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-3.0.0.tgz",
|
||||
"integrity": "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/io": "^3.0.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/http-client": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
|
||||
@@ -53,9 +69,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@actions/io": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
|
||||
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz",
|
||||
"integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
|
||||
+4
-3
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "@graycoreio/github-actions-magento2",
|
||||
"version": "4.0.0",
|
||||
"version": "8.5.0",
|
||||
"description": "Github Actions for Magento 2",
|
||||
"scripts": {
|
||||
"test": "cd supported-version && npm run test && cd -",
|
||||
"test": "cd supported-version && npm run test && cd - && cd setup-install && npm run test && cd -",
|
||||
"release": "standard-version"
|
||||
},
|
||||
"private": true,
|
||||
@@ -18,7 +18,8 @@
|
||||
},
|
||||
"homepage": "https://github.com/graycoreio/github-actions-magento2#readme",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.11.1"
|
||||
"@actions/core": "^1.11.1",
|
||||
"@actions/exec": "^3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.14",
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"bump-minor-pre-major": true,
|
||||
"bump-patch-for-minor-pre-major": true,
|
||||
"draft-pull-request": true,
|
||||
"prerelease": false,
|
||||
"include-component-in-tag": false,
|
||||
"include-v-in-tag": true,
|
||||
"pull-request-title-pattern": "chore: release ${version}",
|
||||
"packages": {
|
||||
".": {
|
||||
"release-type": "node",
|
||||
"versioning": "prerelease",
|
||||
"extra-files": [
|
||||
{ "type": "generic", "path": "*/README.md", "glob": true },
|
||||
{ "type": "generic", "path": "docs/workflows/*.md", "glob": true }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,17 @@
|
||||
"bump-patch-for-minor-pre-major": true,
|
||||
"draft-pull-request": true,
|
||||
"prerelease": true,
|
||||
"prerelease-type": "rc.0",
|
||||
"include-component-in-tag": false,
|
||||
"include-v-in-tag": true,
|
||||
"pull-request-title-pattern": "chore: release ${version}",
|
||||
"packages": {
|
||||
".": {
|
||||
"release-type": "node"
|
||||
"release-type": "node",
|
||||
"extra-files": [
|
||||
{ "type": "generic", "path": "*/README.md", "glob": true },
|
||||
{ "type": "generic", "path": "docs/workflows/*.md", "glob": true }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"bump-minor-pre-major": true,
|
||||
"bump-patch-for-minor-pre-major": true,
|
||||
"draft-pull-request": true,
|
||||
"prerelease": true,
|
||||
"prerelease-type": "rc.0",
|
||||
"include-component-in-tag": false,
|
||||
"include-v-in-tag": true,
|
||||
"pull-request-title-pattern": "chore: release ${version}",
|
||||
"packages": {
|
||||
".": {
|
||||
"release-type": "node",
|
||||
"versioning": "prerelease"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
# "Resolve Check Config" Action
|
||||
|
||||
Reads `.github/check-<kind>.json` (or a path you specify), validates job names against the known list for the selected workflow kind, and emits a per-job filtered version of the `supported-version` matrix. Each job in the output carries an `enabled` flag and its own `matrix`, where every entry's `services` map has been narrowed to the tiers that job actually needs. Consumers gate each job with `fromJSON(...)['<job>'].enabled != false` and feed `fromJSON(...)['<job>'].matrix` into `strategy.matrix`.
|
||||
|
||||
A missing config file is fine — every known job is emitted with its default tier list.
|
||||
|
||||
## Schemas
|
||||
|
||||
Reference the published JSON Schema from your config's `$schema` key for autocompletion and inline validation in editors that support it:
|
||||
|
||||
- [`check-store.schema.json`](./check-store.schema.json) — config for the [MageCheck Store](../docs/workflows/check-store.md) workflow
|
||||
- [`check-extension.schema.json`](./check-extension.schema.json) — config for the [MageCheck Extension](../docs/workflows/check-extension.md) workflow
|
||||
|
||||
## Inputs
|
||||
|
||||
| Input | Description | Required | Default |
|
||||
|---------------|--------------------------------------------------------------------------------------------------------------------------------------------------------|----------|-------------------------------|
|
||||
| `kind` | Which reusable workflow this config belongs to: `store` or `extension`. Selects the default `config_path`, the known-job list, and the per-job tier defaults. | true | |
|
||||
| `matrix` | The matrix JSON emitted by the `supported-version` action. Each entry's `services` map is filtered per-job based on the resolved tier list. | true | |
|
||||
| `config_path` | Path to the check-config JSON file, relative to the runner workspace. | false | `.github/check-<kind>.json` |
|
||||
|
||||
## Usage
|
||||
|
||||
```yml
|
||||
jobs:
|
||||
compute_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
resolved: ${{ steps.resolve.outputs.resolved }}
|
||||
steps:
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@v8.5.0 # x-release-please-version
|
||||
id: supported-version
|
||||
with:
|
||||
kind: currently-supported
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/resolve-check-config@v8.5.0 # x-release-please-version
|
||||
id: resolve
|
||||
with:
|
||||
kind: store
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
|
||||
smoke-test:
|
||||
runs-on: ${{ matrix.os }}
|
||||
needs: compute_matrix
|
||||
if: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['smoke-test'].enabled != false }}
|
||||
services: ${{ matrix.services }}
|
||||
strategy:
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.resolved)['smoke-test'].matrix }}
|
||||
steps:
|
||||
- run: echo "running with ${{ toJSON(matrix.services) }}"
|
||||
```
|
||||
|
||||
Example `.github/check-store.json` for opting out of a specific job:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/graycoreio/github-actions-magento2/main/resolve-check-config/check-store.schema.json",
|
||||
"jobs": {
|
||||
"coding-standard": false
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,27 @@
|
||||
name: "Resolve check config"
|
||||
author: "Graycore"
|
||||
description: "Reads .github/check-<kind>.json (or a path you specify), validates job names against the known list for that workflow kind, and emits a per-job filtered version of the supported-version matrix. Missing config file is treated as 'all jobs enabled with their default tier list.'"
|
||||
|
||||
inputs:
|
||||
kind:
|
||||
required: true
|
||||
description: "Which reusable workflow this config belongs to: `store` or `extension`. Selects the default `config_path`, the known-job list used for validation, and the per-job default tier list."
|
||||
matrix:
|
||||
required: true
|
||||
description: "The matrix JSON emitted by the `supported-version` action. Each entry's `services` map is filtered per-job based on the resolved tier list and embedded in the per-job `matrix` output."
|
||||
config_path:
|
||||
required: false
|
||||
default: ""
|
||||
description: "Path to the check-config JSON file, relative to the runner workspace. Defaults to `.github/check-<kind>.json`. Missing file is fine — every known job is emitted with its default tier list."
|
||||
|
||||
outputs:
|
||||
resolved:
|
||||
description: "The per-job resolved configuration as a JSON object. Each top-level key is a known job name for the selected kind; values are objects with `enabled` (boolean) and `matrix` (a copy of the supported-version matrix where every entry's `services` is filtered to the tiers the job needs). Consumers default-enable omitted jobs via `fromJSON(...)['<job>'].enabled != false` and use `fromJSON(...)['<job>'].matrix` for `strategy.matrix`."
|
||||
|
||||
runs:
|
||||
using: "node24"
|
||||
main: "dist/index.js"
|
||||
|
||||
branding:
|
||||
icon: "check-square"
|
||||
color: "green"
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://raw.githubusercontent.com/graycoreio/github-actions-magento2/main/resolve-check-config/check-extension.schema.json",
|
||||
"title": "graycoreio check-extension config",
|
||||
"description": "Configuration consumed by the check-extension reusable workflow. Per-job toggles and settings live under `jobs`. Top-level remains open for future global keys.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"jobs": {
|
||||
"type": "object",
|
||||
"description": "Per-job configuration. Each key is a job name declared by check-extension; unknown keys are rejected.",
|
||||
"properties": {
|
||||
"unit-test-extension": { "$ref": "#/$defs/jobConfig" },
|
||||
"compile-extension": { "$ref": "#/$defs/jobConfig" },
|
||||
"coding-standard": { "$ref": "#/$defs/jobConfig" },
|
||||
"integration_test": { "$ref": "#/$defs/jobConfig" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": true,
|
||||
"$defs": {
|
||||
"jobConfig": {
|
||||
"description": "How a single job should be configured. Boolean form is shorthand for { enabled: <bool> }; object form allows extra per-job keys.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the job should run. Defaults to true when the key is present.",
|
||||
"default": true
|
||||
},
|
||||
"services": {
|
||||
"type": "array",
|
||||
"description": "Tier names this job needs as GitHub Actions service containers. mysql is always implicit.",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": ["search", "queue", "cache", "web"]
|
||||
},
|
||||
"uniqueItems": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://raw.githubusercontent.com/graycoreio/github-actions-magento2/main/resolve-check-config/check-store.schema.json",
|
||||
"title": "graycoreio check-store config",
|
||||
"description": "Configuration consumed by the check-store reusable workflow. Per-job toggles and settings live under `jobs`. Top-level remains open for future global keys.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"jobs": {
|
||||
"type": "object",
|
||||
"description": "Per-job configuration. Each key is a job name declared by check-store; unknown keys are rejected.",
|
||||
"properties": {
|
||||
"unit-test": { "$ref": "#/$defs/jobConfig" },
|
||||
"coding-standard": { "$ref": "#/$defs/jobConfig" },
|
||||
"smoke-test": { "$ref": "#/$defs/smokeJobConfig" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"additionalProperties": true,
|
||||
"$defs": {
|
||||
"jobConfig": {
|
||||
"description": "How a single job should be configured. Boolean form is shorthand for { enabled: <bool> }; object form allows extra per-job keys.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the job should run. Defaults to true when the key is present.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"smokeJobConfig": {
|
||||
"description": "How the smoke-test job should be configured. Boolean form is shorthand for { enabled: <bool> }; object form adds a `probes` list on top of `enabled`.",
|
||||
"oneOf": [
|
||||
{ "type": "boolean" },
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean",
|
||||
"description": "Whether the job should run. Defaults to true when the key is present.",
|
||||
"default": true
|
||||
},
|
||||
"probes": {
|
||||
"type": "array",
|
||||
"description": "Which smoke-test probes to run. Defaults to [\"page\"]. Add \"graphql\" to also probe the GraphQL endpoint — only for editions that ship GraphQL modules (the mage-os minimal edition does not, so /graphql 404s there).",
|
||||
"items": { "enum": ["page", "graphql"] },
|
||||
"default": ["page"]
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+69
File diff suppressed because one or more lines are too long
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"$schema": "../check-extension.schema.json",
|
||||
"jobs": {
|
||||
"unit-test-extension": true,
|
||||
"compile-extension": true,
|
||||
"coding-standard": true,
|
||||
"integration_test": {
|
||||
"services": ["search", "cache"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "../check-extension.schema.json",
|
||||
"jobs": {
|
||||
"integration_test": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "../check-store.schema.json",
|
||||
"jobs": {
|
||||
"unit-test": true,
|
||||
"coding-standard": true,
|
||||
"integration-test": {
|
||||
"services": ["search", "queue", "cache"]
|
||||
},
|
||||
"smoke-test": {
|
||||
"services": ["search", "queue", "cache", "nginx", "php-fpm"],
|
||||
"probes": ["page", "graphql"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "../check-store.schema.json",
|
||||
"jobs": {
|
||||
"smoke-test": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
module.exports = {
|
||||
clearMocks: true,
|
||||
moduleFileExtensions: ['js', 'ts'],
|
||||
testMatch: ['**/*.spec.ts'],
|
||||
transform: {
|
||||
'^.+\\.ts$': 'ts-jest'
|
||||
},
|
||||
verbose: true
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "@graycoreio/github-actions-magento2-resolve-check-config",
|
||||
"version": "1.0.0",
|
||||
"description": "A Github Action that reads .github/<workflow>.json, validates it against the known job list, and emits resolved per-job configuration.",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "npx esbuild --outfile=dist/index.js --platform=node --bundle --minify src/index.ts",
|
||||
"test": "jest"
|
||||
},
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "0.0.0-PLACEHOLDER"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "0.0.0-PLACEHOLDER",
|
||||
"jest": "0.0.0-PLACEHOLDER",
|
||||
"ts-jest": "0.0.0-PLACEHOLDER"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
import * as core from '@actions/core';
|
||||
import * as fs from 'fs';
|
||||
import * as nodePath from 'path';
|
||||
import { assertKind } from './kind';
|
||||
import { parseMatrixInput, parseRawConfig } from './parse';
|
||||
import { resolveConfig } from './resolve';
|
||||
|
||||
export const run = async (): Promise<void> => {
|
||||
try {
|
||||
const kind = assertKind(core.getInput('kind', { required: true }));
|
||||
const matrix = parseMatrixInput(core.getInput('matrix', { required: true }));
|
||||
const configPath = core.getInput('config_path') || `.github/check-${kind}.json`;
|
||||
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
|
||||
const absolute = nodePath.resolve(workspace, configPath);
|
||||
|
||||
let raw = {};
|
||||
if (fs.existsSync(absolute)) {
|
||||
const text = fs.readFileSync(absolute, 'utf-8');
|
||||
raw = parseRawConfig(text);
|
||||
core.info(`resolve-check-config: read ${absolute}`);
|
||||
} else {
|
||||
core.info(`resolve-check-config: ${absolute} not found — emitting defaults for every known job`);
|
||||
}
|
||||
|
||||
const resolved = resolveConfig(raw, kind, matrix);
|
||||
|
||||
core.setOutput('resolved', JSON.stringify(resolved));
|
||||
} catch (error) {
|
||||
core.setFailed((error as Error).message);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
@@ -0,0 +1,26 @@
|
||||
import { assertKind, isKind } from './kind';
|
||||
|
||||
describe('isKind / assertKind', () => {
|
||||
it('accepts "store"', () => {
|
||||
expect(isKind('store')).toBe(true);
|
||||
expect(assertKind('store')).toBe('store');
|
||||
});
|
||||
|
||||
it('accepts "extension"', () => {
|
||||
expect(isKind('extension')).toBe(true);
|
||||
expect(assertKind('extension')).toBe('extension');
|
||||
});
|
||||
|
||||
it('rejects other strings', () => {
|
||||
expect(isKind('taco')).toBe(false);
|
||||
expect(() => assertKind('taco')).toThrowError(/`kind` must be 'store' or 'extension'/);
|
||||
});
|
||||
|
||||
it('rejects empty input', () => {
|
||||
expect(() => assertKind('')).toThrowError(/`kind` must be 'store' or 'extension'/);
|
||||
});
|
||||
|
||||
it('rejects non-string input', () => {
|
||||
expect(() => assertKind(undefined)).toThrowError(/`kind` must be 'store' or 'extension'/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Kind } from './types';
|
||||
|
||||
/**
|
||||
* Type guard for the `kind` input. Use this when you have an
|
||||
* `unknown` value (e.g. from `core.getInput`) and want to narrow it
|
||||
* without throwing.
|
||||
*/
|
||||
export const isKind = (value: unknown): value is Kind =>
|
||||
value === 'store' || value === 'extension';
|
||||
|
||||
/**
|
||||
* Narrows an `unknown` (typically the raw action input) to `Kind` or
|
||||
* throws a user-facing error naming the accepted values. Prefer this
|
||||
* at the action boundary so a bad `kind` fails fast with a clear
|
||||
* message rather than later as an obscure dispatch miss.
|
||||
*/
|
||||
export const assertKind = (value: unknown): Kind => {
|
||||
if (!isKind(value)) {
|
||||
throw new Error(`check-config: \`kind\` must be 'store' or 'extension' (got ${JSON.stringify(value)})`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { EXTENSION_JOBS, KNOWN_JOBS_EXTENSION, resolveExtensionConfig } from './extension';
|
||||
import { Matrix } from '../types';
|
||||
|
||||
const FULL_SERVICES = {
|
||||
mysql: { image: 'mysql:8' },
|
||||
opensearch: { image: 'opensearchproject/opensearch:2' },
|
||||
rabbitmq: { image: 'rabbitmq:3' },
|
||||
valkey: { image: 'valkey:8' },
|
||||
nginx: { image: 'nginx:1.27' },
|
||||
'php-fpm': { image: 'php:8.3-fpm' },
|
||||
};
|
||||
|
||||
const MATRIX: Matrix = {
|
||||
include: [{ php: '8.3', services: { ...FULL_SERVICES } }],
|
||||
};
|
||||
|
||||
describe('EXTENSION_JOBS', () => {
|
||||
it('declares the check-extension jobs', () => {
|
||||
expect(Object.keys(EXTENSION_JOBS).sort()).toEqual([
|
||||
'coding-standard',
|
||||
'compile-extension',
|
||||
'integration_test',
|
||||
'unit-test-extension',
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps KNOWN_JOBS_EXTENSION in sync with the map keys', () => {
|
||||
expect([...KNOWN_JOBS_EXTENSION].sort()).toEqual(Object.keys(EXTENSION_JOBS).sort());
|
||||
});
|
||||
|
||||
it('declares integration_test required tiers (no web)', () => {
|
||||
expect(EXTENSION_JOBS['integration_test'].services).toEqual([]);
|
||||
expect([...EXTENSION_JOBS['integration_test'].requiredServices!].sort()).toEqual([
|
||||
'cache',
|
||||
'db',
|
||||
'queue',
|
||||
'search',
|
||||
]);
|
||||
});
|
||||
|
||||
it('leaves the non-service jobs with empty defaults', () => {
|
||||
for (const name of ['unit-test-extension', 'compile-extension', 'coding-standard']) {
|
||||
expect(EXTENSION_JOBS[name].services).toEqual([]);
|
||||
expect(EXTENSION_JOBS[name].requiredServices).toBeUndefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveExtensionConfig', () => {
|
||||
it('emits every known job', () => {
|
||||
const resolved = resolveExtensionConfig({}, MATRIX);
|
||||
expect(Object.keys(resolved).sort()).toEqual([
|
||||
'coding-standard',
|
||||
'compile-extension',
|
||||
'integration_test',
|
||||
'unit-test-extension',
|
||||
]);
|
||||
});
|
||||
|
||||
it('emits services={} for the non-service jobs', () => {
|
||||
const resolved = resolveExtensionConfig({}, MATRIX);
|
||||
for (const name of ['unit-test-extension', 'compile-extension', 'coding-standard']) {
|
||||
expect(resolved[name].matrix.include[0].services).toEqual({});
|
||||
}
|
||||
});
|
||||
|
||||
it('integration_test includes mysql/search/queue/cache but NOT nginx/php-fpm', () => {
|
||||
const resolved = resolveExtensionConfig({}, MATRIX);
|
||||
expect(Object.keys(resolved['integration_test'].matrix.include[0].services!).sort()).toEqual([
|
||||
'mysql',
|
||||
'opensearch',
|
||||
'rabbitmq',
|
||||
'valkey',
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps integration_test required tiers even when caller overrides services to []', () => {
|
||||
const resolved = resolveExtensionConfig(
|
||||
{ jobs: { integration_test: { services: [] } } },
|
||||
MATRIX,
|
||||
);
|
||||
expect(Object.keys(resolved['integration_test'].matrix.include[0].services!).sort()).toEqual([
|
||||
'mysql',
|
||||
'opensearch',
|
||||
'rabbitmq',
|
||||
'valkey',
|
||||
]);
|
||||
});
|
||||
|
||||
it('throws on a typo in the job name', () => {
|
||||
expect(() => resolveExtensionConfig({ jobs: { 'inteegration_test': false } }, MATRIX)).toThrowError(
|
||||
/unknown job "inteegration_test" for kind "extension"/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when a store-only job name is used', () => {
|
||||
expect(() => resolveExtensionConfig({ jobs: { 'smoke-test': false } }, MATRIX)).toThrowError(
|
||||
/unknown job "smoke-test" for kind "extension"/
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { resolveJobs } from '../parse';
|
||||
import { JobDefaults, Matrix, RawConfig, ResolvedConfig } from '../types';
|
||||
|
||||
/**
|
||||
* Per-job defaults for the `check-extension.yaml` reusable workflow.
|
||||
* Edit this map when a job is added, removed, or renamed in that
|
||||
* workflow — keys are validated against caller config and the values
|
||||
* supply the default tier list used when the caller doesn't override
|
||||
* `services` themselves.
|
||||
*/
|
||||
export const EXTENSION_JOBS: Record<string, JobDefaults> = {
|
||||
'unit-test-extension': { services: [] },
|
||||
'compile-extension': { services: [] },
|
||||
'coding-standard': { services: [] },
|
||||
'integration_test': {
|
||||
services: [],
|
||||
requiredServices: ['db', 'search', 'queue', 'cache'],
|
||||
},
|
||||
};
|
||||
|
||||
export const KNOWN_JOBS_EXTENSION: readonly string[] = Object.keys(EXTENSION_JOBS);
|
||||
|
||||
/**
|
||||
* Resolves a parsed config file + supported-version matrix against
|
||||
* the check-extension job list. Thin wrapper that binds the kind and
|
||||
* the per-job defaults so callers don't repeat the wiring.
|
||||
*/
|
||||
export const resolveExtensionConfig = (raw: RawConfig, matrix: Matrix): ResolvedConfig =>
|
||||
resolveJobs(raw, 'extension', EXTENSION_JOBS, matrix);
|
||||
@@ -0,0 +1,122 @@
|
||||
import { KNOWN_JOBS_STORE, resolveStoreConfig, STORE_JOBS } from './store';
|
||||
import { Matrix } from '../types';
|
||||
|
||||
const MATRIX: Matrix = {
|
||||
include: [{
|
||||
php: '8.3',
|
||||
services: {
|
||||
mysql: { image: 'mysql:8' },
|
||||
opensearch: { image: 'opensearchproject/opensearch:2' },
|
||||
rabbitmq: { image: 'rabbitmq:3' },
|
||||
valkey: { image: 'valkey:8' },
|
||||
nginx: { image: 'nginx:1.27' },
|
||||
'php-fpm': { image: 'php:8.3-fpm' },
|
||||
},
|
||||
}],
|
||||
};
|
||||
|
||||
describe('STORE_JOBS', () => {
|
||||
it('declares the check-store jobs', () => {
|
||||
expect(Object.keys(STORE_JOBS).sort()).toEqual(['coding-standard', 'smoke-test', 'unit-test']);
|
||||
});
|
||||
|
||||
it('declares smoke-test required tiers (end-user cannot toggle)', () => {
|
||||
expect(STORE_JOBS['smoke-test'].services).toEqual([]);
|
||||
expect([...STORE_JOBS['smoke-test'].requiredServices!].sort()).toEqual([
|
||||
'cache',
|
||||
'db',
|
||||
'queue',
|
||||
'search',
|
||||
'web',
|
||||
]);
|
||||
});
|
||||
|
||||
it('defaults smoke-test to the page probe only (graphql is opt-in)', () => {
|
||||
expect(STORE_JOBS['smoke-test'].probes).toEqual(['page']);
|
||||
});
|
||||
|
||||
it('exposes empty service defaults for unit-test and coding-standard', () => {
|
||||
expect(STORE_JOBS['unit-test'].services).toEqual([]);
|
||||
expect(STORE_JOBS['coding-standard'].services).toEqual([]);
|
||||
});
|
||||
|
||||
it('keeps KNOWN_JOBS_STORE in sync with the map keys', () => {
|
||||
expect([...KNOWN_JOBS_STORE].sort()).toEqual(Object.keys(STORE_JOBS).sort());
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveStoreConfig', () => {
|
||||
it('emits every known job with default tier expansion, always including mysql for smoke-test', () => {
|
||||
const resolved = resolveStoreConfig({}, MATRIX);
|
||||
expect(Object.keys(resolved).sort()).toEqual(['coding-standard', 'smoke-test', 'unit-test']);
|
||||
expect(resolved['unit-test'].matrix.include[0].services).toEqual({});
|
||||
expect(Object.keys(resolved['smoke-test'].matrix.include[0].services!).sort()).toEqual([
|
||||
'mysql',
|
||||
'nginx',
|
||||
'opensearch',
|
||||
'php-fpm',
|
||||
'rabbitmq',
|
||||
'valkey',
|
||||
]);
|
||||
});
|
||||
|
||||
it('keeps every required service even when caller overrides smoke-test services to []', () => {
|
||||
const resolved = resolveStoreConfig(
|
||||
{ jobs: { 'smoke-test': { services: [] } } },
|
||||
MATRIX,
|
||||
);
|
||||
expect(Object.keys(resolved['smoke-test'].matrix.include[0].services!).sort()).toEqual([
|
||||
'mysql',
|
||||
'nginx',
|
||||
'opensearch',
|
||||
'php-fpm',
|
||||
'rabbitmq',
|
||||
'valkey',
|
||||
]);
|
||||
});
|
||||
|
||||
it('honors enabled=false for a job', () => {
|
||||
const resolved = resolveStoreConfig(
|
||||
{ jobs: { 'smoke-test': false } },
|
||||
MATRIX,
|
||||
);
|
||||
expect(resolved['smoke-test'].enabled).toBe(false);
|
||||
});
|
||||
|
||||
it('emits the default page-only probe list for smoke-test', () => {
|
||||
const resolved = resolveStoreConfig({}, MATRIX);
|
||||
expect(resolved['smoke-test'].probes).toEqual(['page']);
|
||||
});
|
||||
|
||||
it('honors a smoke-test probes override', () => {
|
||||
const resolved = resolveStoreConfig(
|
||||
{ jobs: { 'smoke-test': { probes: ['page', 'graphql'] } } },
|
||||
MATRIX,
|
||||
);
|
||||
expect(resolved['smoke-test'].probes).toEqual(['page', 'graphql']);
|
||||
});
|
||||
|
||||
it('does not emit probes on jobs without a probe concept', () => {
|
||||
const resolved = resolveStoreConfig({}, MATRIX);
|
||||
expect(resolved['unit-test'].probes).toBeUndefined();
|
||||
expect(resolved['coding-standard'].probes).toBeUndefined();
|
||||
});
|
||||
|
||||
it('rejects probes on a job that does not support it', () => {
|
||||
expect(() => resolveStoreConfig({ jobs: { 'unit-test': { probes: ['page'] } } }, MATRIX)).toThrowError(
|
||||
/job "unit-test" does not support "probes"/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws on a typo in the job name', () => {
|
||||
expect(() => resolveStoreConfig({ jobs: { 'smkoe-test': false } }, MATRIX)).toThrowError(
|
||||
/unknown job "smkoe-test" for kind "store"/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when an extension-only job name is used', () => {
|
||||
expect(() => resolveStoreConfig({ jobs: { 'unit-test-extension': false } }, MATRIX)).toThrowError(
|
||||
/unknown job "unit-test-extension" for kind "store"/
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import { resolveJobs } from '../parse';
|
||||
import { JobDefaults, Matrix, RawConfig, ResolvedConfig } from '../types';
|
||||
|
||||
/**
|
||||
* Per-job defaults for the `check-store.yaml` reusable workflow.
|
||||
* Edit this map when a job is added, removed, or renamed in that
|
||||
* workflow — keys are validated against caller config and the values
|
||||
* supply the default tier list used when the caller doesn't override
|
||||
* `services` themselves.
|
||||
*/
|
||||
export const STORE_JOBS: Record<string, JobDefaults> = {
|
||||
'unit-test': { services: [] },
|
||||
'coding-standard': { services: [] },
|
||||
'smoke-test': {
|
||||
services: [],
|
||||
requiredServices: ['db', 'search', 'queue', 'cache', 'web'],
|
||||
probes: ['page'],
|
||||
},
|
||||
};
|
||||
|
||||
export const KNOWN_JOBS_STORE: readonly string[] = Object.keys(STORE_JOBS);
|
||||
|
||||
/**
|
||||
* Resolves a parsed config file + supported-version matrix against
|
||||
* the check-store job list. Thin wrapper that binds the kind and the
|
||||
* per-job defaults so callers don't repeat the wiring.
|
||||
*/
|
||||
export const resolveStoreConfig = (raw: RawConfig, matrix: Matrix): ResolvedConfig =>
|
||||
resolveJobs(raw, 'store', STORE_JOBS, matrix);
|
||||
@@ -0,0 +1,367 @@
|
||||
import {
|
||||
filterEntryServices,
|
||||
filterMatrixForJob,
|
||||
mergeRequiredTiers,
|
||||
normalizeJobEntry,
|
||||
normalizeProbes,
|
||||
parseMatrixInput,
|
||||
parseRawConfig,
|
||||
resolveJobs,
|
||||
} from './parse';
|
||||
import { JobDefaults, Matrix } from './types';
|
||||
|
||||
const FULL_SERVICES = {
|
||||
mysql: { image: 'mysql:8' },
|
||||
opensearch: { image: 'opensearchproject/opensearch:2' },
|
||||
rabbitmq: { image: 'rabbitmq:3' },
|
||||
valkey: { image: 'valkey:8' },
|
||||
nginx: { image: 'nginx:1.27' },
|
||||
'php-fpm': { image: 'php:8.3-fpm' },
|
||||
};
|
||||
|
||||
const MATRIX: Matrix = {
|
||||
include: [{ php: '8.3', services: { ...FULL_SERVICES } }],
|
||||
};
|
||||
|
||||
const noDefaults: JobDefaults = { services: [] };
|
||||
const smokeDefaults: JobDefaults = { services: ['search', 'queue', 'cache', 'web'] };
|
||||
const probeDefaults: JobDefaults = { services: [], probes: ['page'] };
|
||||
|
||||
describe('normalizeJobEntry', () => {
|
||||
it('defaults enabled=true and uses the default tiers when entry is undefined', () => {
|
||||
expect(normalizeJobEntry('smoke-test', undefined, smokeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: smokeDefaults.services,
|
||||
});
|
||||
});
|
||||
|
||||
it('treats true shorthand as enabled with defaults', () => {
|
||||
expect(normalizeJobEntry('smoke-test', true, smokeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: smokeDefaults.services,
|
||||
});
|
||||
});
|
||||
|
||||
it('treats false shorthand as disabled with defaults', () => {
|
||||
expect(normalizeJobEntry('smoke-test', false, smokeDefaults)).toEqual({
|
||||
enabled: false,
|
||||
tiers: smokeDefaults.services,
|
||||
});
|
||||
});
|
||||
|
||||
it('empty object is enabled with defaults', () => {
|
||||
expect(normalizeJobEntry('smoke-test', {}, smokeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: smokeDefaults.services,
|
||||
});
|
||||
});
|
||||
|
||||
it('preserves enabled when explicitly set', () => {
|
||||
expect(normalizeJobEntry('smoke-test', { enabled: false }, smokeDefaults)).toEqual({
|
||||
enabled: false,
|
||||
tiers: smokeDefaults.services,
|
||||
});
|
||||
});
|
||||
|
||||
it('overrides the default tiers when services is set', () => {
|
||||
expect(normalizeJobEntry('smoke-test', { services: ['cache', 'web'] }, smokeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: ['cache', 'web'],
|
||||
});
|
||||
});
|
||||
|
||||
it('accepts an empty services array as "no services"', () => {
|
||||
expect(normalizeJobEntry('smoke-test', { services: [] }, smokeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('throws when entry is a non-array primitive other than boolean', () => {
|
||||
expect(() => normalizeJobEntry('unit-test', 'true' as never, noDefaults)).toThrowError(
|
||||
/must be a boolean or an object/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when entry is an array', () => {
|
||||
expect(() => normalizeJobEntry('unit-test', [] as never, noDefaults)).toThrowError(/got array/);
|
||||
});
|
||||
|
||||
it('throws when services is not an array', () => {
|
||||
expect(() => normalizeJobEntry('smoke-test', { services: 'search' } as never, smokeDefaults)).toThrowError(
|
||||
/services must be an array of tier names/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when services contains an unknown tier', () => {
|
||||
expect(() => normalizeJobEntry('smoke-test', { services: ['llm'] } as never, smokeDefaults)).toThrowError(
|
||||
/services contains unknown tier "llm"/
|
||||
);
|
||||
});
|
||||
|
||||
it('carries the default probes when the entry omits them', () => {
|
||||
expect(normalizeJobEntry('smoke-test', { services: [] }, probeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: [],
|
||||
probes: ['page'],
|
||||
});
|
||||
});
|
||||
|
||||
it('carries the default probes for the boolean shorthand', () => {
|
||||
expect(normalizeJobEntry('smoke-test', true, probeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: [],
|
||||
probes: ['page'],
|
||||
});
|
||||
});
|
||||
|
||||
it('overrides the default probes when probes is set', () => {
|
||||
expect(normalizeJobEntry('smoke-test', { probes: ['page', 'graphql'] }, probeDefaults)).toEqual({
|
||||
enabled: true,
|
||||
tiers: [],
|
||||
probes: ['page', 'graphql'],
|
||||
});
|
||||
});
|
||||
|
||||
it('omits probes for a job that declares no probe defaults', () => {
|
||||
expect(normalizeJobEntry('unit-test', { services: [] }, noDefaults).probes).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('normalizeProbes', () => {
|
||||
it('returns the defaults when probes is omitted', () => {
|
||||
expect(normalizeProbes('smoke-test', undefined, ['page'])).toEqual(['page']);
|
||||
});
|
||||
|
||||
it('returns undefined for a job with no probe defaults when omitted', () => {
|
||||
expect(normalizeProbes('unit-test', undefined, undefined)).toBeUndefined();
|
||||
});
|
||||
|
||||
it('throws when probes is set on a job that does not support it', () => {
|
||||
expect(() => normalizeProbes('unit-test', ['page'], undefined)).toThrowError(
|
||||
/job "unit-test" does not support "probes"/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when probes is not an array', () => {
|
||||
expect(() => normalizeProbes('smoke-test', 'page', ['page'])).toThrowError(
|
||||
/probes must be an array of probe names/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when probes contains an unknown probe', () => {
|
||||
expect(() => normalizeProbes('smoke-test', ['rest'], ['page'])).toThrowError(
|
||||
/probes contains unknown probe "rest"/
|
||||
);
|
||||
});
|
||||
|
||||
it('accepts an empty probes array', () => {
|
||||
expect(normalizeProbes('smoke-test', [], ['page'])).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mergeRequiredTiers', () => {
|
||||
it('returns the input list when required is undefined', () => {
|
||||
expect(mergeRequiredTiers(['cache'], undefined)).toEqual(['cache']);
|
||||
});
|
||||
|
||||
it('returns the input list when required is empty', () => {
|
||||
expect(mergeRequiredTiers(['cache'], [])).toEqual(['cache']);
|
||||
});
|
||||
|
||||
it('prepends required tiers ahead of the input tiers', () => {
|
||||
expect(mergeRequiredTiers(['cache', 'web'], ['db'])).toEqual(['db', 'cache', 'web']);
|
||||
});
|
||||
|
||||
it('deduplicates when a required tier already appears in the input', () => {
|
||||
expect(mergeRequiredTiers(['db', 'cache'], ['db'])).toEqual(['db', 'cache']);
|
||||
});
|
||||
|
||||
it('deduplicates within required itself', () => {
|
||||
expect(mergeRequiredTiers(['cache'], ['db', 'db'])).toEqual(['db', 'cache']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterEntryServices', () => {
|
||||
it('returns services={} for an empty tier list', () => {
|
||||
const out = filterEntryServices({ php: '8.3', services: FULL_SERVICES }, []);
|
||||
expect(out.services).toEqual({});
|
||||
expect(out.php).toBe('8.3');
|
||||
});
|
||||
|
||||
it('keeps only services in the requested tiers', () => {
|
||||
const out = filterEntryServices({ php: '8.3', services: FULL_SERVICES }, ['cache', 'web']);
|
||||
expect(Object.keys(out.services!).sort()).toEqual(['nginx', 'php-fpm', 'valkey']);
|
||||
});
|
||||
|
||||
it('drops services that the matrix doesn\'t carry (elasticsearch absent)', () => {
|
||||
const out = filterEntryServices({ services: { opensearch: FULL_SERVICES.opensearch } }, ['search']);
|
||||
expect(Object.keys(out.services!)).toEqual(['opensearch']);
|
||||
});
|
||||
|
||||
it('emits services={} when the entry has no services map', () => {
|
||||
const out = filterEntryServices({ php: '8.3' }, ['cache']);
|
||||
expect(out.services).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('filterMatrixForJob', () => {
|
||||
it('preserves matrix shape, mapping every entry through filterEntryServices', () => {
|
||||
const out = filterMatrixForJob(MATRIX, ['queue']);
|
||||
expect(out.include).toHaveLength(1);
|
||||
expect(Object.keys(out.include[0].services!)).toEqual(['rabbitmq']);
|
||||
});
|
||||
|
||||
it('passes through unrelated top-level matrix keys', () => {
|
||||
const out = filterMatrixForJob({ ...MATRIX, magento: ['2.4.7'] } as Matrix, []);
|
||||
expect((out as Matrix).magento).toEqual(['2.4.7']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('resolveJobs', () => {
|
||||
const jobs: Record<string, JobDefaults> = {
|
||||
'unit-test': noDefaults,
|
||||
'smoke-test': smokeDefaults,
|
||||
};
|
||||
|
||||
it('emits every known job, defaulted-enabled, when raw is empty', () => {
|
||||
const out = resolveJobs({}, 'store', jobs, MATRIX);
|
||||
expect(Object.keys(out).sort()).toEqual(['smoke-test', 'unit-test']);
|
||||
expect(out['unit-test'].enabled).toBe(true);
|
||||
expect(out['smoke-test'].enabled).toBe(true);
|
||||
});
|
||||
|
||||
it('emits services={} on entries for a no-default job', () => {
|
||||
const out = resolveJobs({}, 'store', jobs, MATRIX);
|
||||
expect(out['unit-test'].matrix.include[0].services).toEqual({});
|
||||
});
|
||||
|
||||
it('expands the smoke-test default tiers across the matrix entry', () => {
|
||||
const out = resolveJobs({}, 'store', jobs, MATRIX);
|
||||
expect(Object.keys(out['smoke-test'].matrix.include[0].services!).sort()).toEqual([
|
||||
'nginx',
|
||||
'opensearch',
|
||||
'php-fpm',
|
||||
'rabbitmq',
|
||||
'valkey',
|
||||
]);
|
||||
});
|
||||
|
||||
it('applies a caller-supplied services override', () => {
|
||||
const out = resolveJobs(
|
||||
{ jobs: { 'smoke-test': { services: ['cache'] } } },
|
||||
'store',
|
||||
jobs,
|
||||
MATRIX,
|
||||
);
|
||||
expect(Object.keys(out['smoke-test'].matrix.include[0].services!)).toEqual(['valkey']);
|
||||
});
|
||||
|
||||
it('always merges requiredServices into the matrix even when caller overrides services', () => {
|
||||
const withRequired: Record<string, JobDefaults> = {
|
||||
'smoke-test': { ...smokeDefaults, requiredServices: ['db'] },
|
||||
};
|
||||
const out = resolveJobs(
|
||||
{ jobs: { 'smoke-test': { services: ['cache'] } } },
|
||||
'store',
|
||||
withRequired,
|
||||
MATRIX,
|
||||
);
|
||||
expect(Object.keys(out['smoke-test'].matrix.include[0].services!).sort()).toEqual(['mysql', 'valkey']);
|
||||
});
|
||||
|
||||
it('keeps requiredServices even when caller overrides services to []', () => {
|
||||
const withRequired: Record<string, JobDefaults> = {
|
||||
'smoke-test': { ...smokeDefaults, requiredServices: ['db'] },
|
||||
};
|
||||
const out = resolveJobs(
|
||||
{ jobs: { 'smoke-test': { services: [] } } },
|
||||
'store',
|
||||
withRequired,
|
||||
MATRIX,
|
||||
);
|
||||
expect(Object.keys(out['smoke-test'].matrix.include[0].services!)).toEqual(['mysql']);
|
||||
});
|
||||
|
||||
it('honors caller enabled=false but still emits a filtered matrix', () => {
|
||||
const out = resolveJobs(
|
||||
{ jobs: { 'smoke-test': false } },
|
||||
'store',
|
||||
jobs,
|
||||
MATRIX,
|
||||
);
|
||||
expect(out['smoke-test'].enabled).toBe(false);
|
||||
expect(out['smoke-test'].matrix.include[0].services).toBeDefined();
|
||||
});
|
||||
|
||||
it('throws on unknown job names with the kind in the message', () => {
|
||||
expect(() => resolveJobs({ jobs: { taco: false } }, 'store', jobs, MATRIX)).toThrowError(
|
||||
/unknown job "taco" for kind "store"/
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when `jobs` is not an object', () => {
|
||||
expect(() => resolveJobs({ jobs: 'oops' } as never, 'store', jobs, MATRIX)).toThrowError(
|
||||
/`jobs` must be an object/
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseRawConfig', () => {
|
||||
it('returns an empty object for empty input', () => {
|
||||
expect(parseRawConfig('')).toEqual({});
|
||||
});
|
||||
|
||||
it('returns an empty object for whitespace input', () => {
|
||||
expect(parseRawConfig(' \n ')).toEqual({});
|
||||
});
|
||||
|
||||
it('parses a valid object', () => {
|
||||
expect(parseRawConfig('{"jobs": {"unit-test": true}}')).toEqual({
|
||||
jobs: { 'unit-test': true },
|
||||
});
|
||||
});
|
||||
|
||||
it('throws on syntactically invalid JSON', () => {
|
||||
expect(() => parseRawConfig('{not json}')).toThrowError(/failed to parse JSON/);
|
||||
});
|
||||
|
||||
it('throws when top level is an array', () => {
|
||||
expect(() => parseRawConfig('[]')).toThrowError(/top-level value must be an object/);
|
||||
});
|
||||
|
||||
it('throws when top level is a primitive', () => {
|
||||
expect(() => parseRawConfig('"hello"')).toThrowError(/top-level value must be an object/);
|
||||
});
|
||||
|
||||
it('throws when top level is null', () => {
|
||||
expect(() => parseRawConfig('null')).toThrowError(/top-level value must be an object/);
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseMatrixInput', () => {
|
||||
it('parses a valid matrix', () => {
|
||||
const out = parseMatrixInput('{"include": [{"php": "8.3"}]}');
|
||||
expect(out.include).toEqual([{ php: '8.3' }]);
|
||||
});
|
||||
|
||||
it('throws on empty input', () => {
|
||||
expect(() => parseMatrixInput('')).toThrowError(/`matrix` input is required/);
|
||||
});
|
||||
|
||||
it('throws on invalid JSON', () => {
|
||||
expect(() => parseMatrixInput('{nope}')).toThrowError(/failed to parse `matrix` input/);
|
||||
});
|
||||
|
||||
it('throws when top level is an array', () => {
|
||||
expect(() => parseMatrixInput('[]')).toThrowError(/`matrix` must be a JSON object/);
|
||||
});
|
||||
|
||||
it('throws when include is missing', () => {
|
||||
expect(() => parseMatrixInput('{}')).toThrowError(/`matrix.include` must be an array/);
|
||||
});
|
||||
|
||||
it('throws when include is not an array', () => {
|
||||
expect(() => parseMatrixInput('{"include": "nope"}')).toThrowError(/`matrix.include` must be an array/);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,211 @@
|
||||
import { JobDefaults, Kind, Matrix, MatrixEntry, RawConfig, RawJobConfig, ResolvedConfig, ResolvedJobConfig, Services } from './types';
|
||||
import { isTier, servicesForTiers, Tier } from './tier-map';
|
||||
import { isProbe, Probe } from './probe';
|
||||
|
||||
/**
|
||||
* Normalizes the `probes` value from a job entry. Returns the
|
||||
* caller's list when present (validated), the job's default probe
|
||||
* list when omitted, or `undefined` for jobs that have no probe
|
||||
* concept. Throws if a job without probe defaults is given `probes`.
|
||||
*/
|
||||
export const normalizeProbes = (
|
||||
jobName: string,
|
||||
raw: unknown,
|
||||
defaults: readonly Probe[] | undefined,
|
||||
): readonly Probe[] | undefined => {
|
||||
if (raw === undefined) {
|
||||
return defaults;
|
||||
}
|
||||
if (defaults === undefined) {
|
||||
throw new Error(`check-config: job "${jobName}" does not support "probes"`);
|
||||
}
|
||||
if (!Array.isArray(raw)) {
|
||||
throw new Error(`check-config: job "${jobName}".probes must be an array of probe names`);
|
||||
}
|
||||
const probes: Probe[] = [];
|
||||
for (const value of raw) {
|
||||
if (!isProbe(value)) {
|
||||
throw new Error(`check-config: job "${jobName}".probes contains unknown probe "${String(value)}"`);
|
||||
}
|
||||
probes.push(value);
|
||||
}
|
||||
return probes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes a single raw job entry to (enabled, tiers, probes).
|
||||
* Accepts the boolean shorthand and the object form. Validates the
|
||||
* shape, the `services` tier list, and the `probes` list; throws on
|
||||
* unexpected input. The caller supplies the per-job defaults, used
|
||||
* when `services`/`probes` are omitted from the entry. `probes` is
|
||||
* `undefined` for jobs that declare no probe defaults.
|
||||
*/
|
||||
export const normalizeJobEntry = (
|
||||
jobName: string,
|
||||
raw: RawJobConfig | undefined,
|
||||
defaults: JobDefaults,
|
||||
): { enabled: boolean; tiers: readonly Tier[]; probes?: readonly Probe[] } => {
|
||||
if (raw === undefined) {
|
||||
return { enabled: true, tiers: defaults.services, probes: defaults.probes };
|
||||
}
|
||||
if (typeof raw === 'boolean') {
|
||||
return { enabled: raw, tiers: defaults.services, probes: defaults.probes };
|
||||
}
|
||||
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
||||
throw new Error(
|
||||
`check-config: job "${jobName}" must be a boolean or an object (got ${Array.isArray(raw) ? 'array' : typeof raw})`
|
||||
);
|
||||
}
|
||||
const { enabled, services, probes } = raw as { enabled?: unknown; services?: unknown; probes?: unknown };
|
||||
const enabledValue = enabled === undefined ? true : Boolean(enabled);
|
||||
const resolvedProbes = normalizeProbes(jobName, probes, defaults.probes);
|
||||
|
||||
if (services === undefined) {
|
||||
return { enabled: enabledValue, tiers: defaults.services, probes: resolvedProbes };
|
||||
}
|
||||
if (!Array.isArray(services)) {
|
||||
throw new Error(`check-config: job "${jobName}".services must be an array of tier names`);
|
||||
}
|
||||
const tiers: Tier[] = [];
|
||||
for (const value of services) {
|
||||
if (!isTier(value)) {
|
||||
throw new Error(`check-config: job "${jobName}".services contains unknown tier "${String(value)}"`);
|
||||
}
|
||||
tiers.push(value);
|
||||
}
|
||||
return { enabled: enabledValue, tiers, probes: resolvedProbes };
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges a job's `requiredServices` into the resolved tier list,
|
||||
* deduplicating while preserving order (required tiers first, then
|
||||
* the caller/default tiers in their original order).
|
||||
*/
|
||||
export const mergeRequiredTiers = (
|
||||
tiers: readonly Tier[],
|
||||
required: readonly Tier[] | undefined,
|
||||
): readonly Tier[] => {
|
||||
if (!required || required.length === 0) return tiers;
|
||||
const seen = new Set<Tier>();
|
||||
const merged: Tier[] = [];
|
||||
for (const tier of required) {
|
||||
if (!seen.has(tier)) { seen.add(tier); merged.push(tier); }
|
||||
}
|
||||
for (const tier of tiers) {
|
||||
if (!seen.has(tier)) { seen.add(tier); merged.push(tier); }
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of `entry` with `services` filtered to the concrete
|
||||
* names produced by expanding `tiers` through the tier-map. An empty
|
||||
* tier list yields `services: {}`.
|
||||
*/
|
||||
export const filterEntryServices = (entry: MatrixEntry, tiers: readonly Tier[]): MatrixEntry => {
|
||||
const keep = servicesForTiers(tiers);
|
||||
const original = entry.services ?? {};
|
||||
const filtered: Services = {};
|
||||
for (const [name, config] of Object.entries(original)) {
|
||||
if (keep.has(name)) filtered[name] = config;
|
||||
}
|
||||
return { ...entry, services: filtered };
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-job filter applied to the supported-version matrix: returns a
|
||||
* shallow clone with every entry's `services` narrowed to the tiers
|
||||
* the job needs.
|
||||
*/
|
||||
export const filterMatrixForJob = (matrix: Matrix, tiers: readonly Tier[]): Matrix => ({
|
||||
...matrix,
|
||||
include: matrix.include.map(entry => filterEntryServices(entry, tiers)),
|
||||
});
|
||||
|
||||
/**
|
||||
* Shared per-kind resolver: walks the per-kind job map and emits one
|
||||
* `ResolvedJobConfig` per known job. Caller-supplied jobs override
|
||||
* the defaults; jobs the caller omitted still appear, carrying the
|
||||
* default `enabled: true` and the default tier list. Rejects unknown
|
||||
* job names from the config so typos surface in CI.
|
||||
*/
|
||||
export const resolveJobs = (
|
||||
raw: RawConfig,
|
||||
kind: Kind,
|
||||
jobs: Record<string, JobDefaults>,
|
||||
matrix: Matrix,
|
||||
): ResolvedConfig => {
|
||||
const rawJobs = raw.jobs ?? {};
|
||||
if (rawJobs === null || typeof rawJobs !== 'object' || Array.isArray(rawJobs)) {
|
||||
throw new Error(`check-config: \`jobs\` must be an object`);
|
||||
}
|
||||
for (const name of Object.keys(rawJobs)) {
|
||||
if (!(name in jobs)) {
|
||||
throw new Error(
|
||||
`check-config: unknown job "${name}" for kind "${kind}". Known jobs: ${Object.keys(jobs).join(', ')}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const resolved: ResolvedConfig = {};
|
||||
for (const [name, defaults] of Object.entries(jobs)) {
|
||||
const entry = (rawJobs as Record<string, RawJobConfig>)[name];
|
||||
const { enabled, tiers, probes } = normalizeJobEntry(name, entry, defaults);
|
||||
const finalTiers = mergeRequiredTiers(tiers, defaults.requiredServices);
|
||||
const resolvedEntry: ResolvedJobConfig = {
|
||||
enabled,
|
||||
matrix: filterMatrixForJob(matrix, finalTiers),
|
||||
};
|
||||
if (probes !== undefined) {
|
||||
resolvedEntry.probes = [...probes];
|
||||
}
|
||||
resolved[name] = resolvedEntry;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a JSON string into a RawConfig with shape validation
|
||||
* (must be an object, not an array or primitive). Empty/whitespace
|
||||
* input yields an empty config.
|
||||
*/
|
||||
export const parseRawConfig = (jsonText: string): RawConfig => {
|
||||
const trimmed = jsonText.trim();
|
||||
if (trimmed === '') return {};
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(trimmed);
|
||||
} catch (e) {
|
||||
throw new Error(`check-config: failed to parse JSON: ${(e as Error).message}`);
|
||||
}
|
||||
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
throw new Error(`check-config: top-level value must be an object`);
|
||||
}
|
||||
return parsed as RawConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the `matrix` action input. Validates the top-level shape
|
||||
* (must be an object with an `include` array) so a malformed input
|
||||
* fails with a clear message at the boundary.
|
||||
*/
|
||||
export const parseMatrixInput = (jsonText: string): Matrix => {
|
||||
const trimmed = jsonText.trim();
|
||||
if (trimmed === '') {
|
||||
throw new Error('check-config: `matrix` input is required');
|
||||
}
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(trimmed);
|
||||
} catch (e) {
|
||||
throw new Error(`check-config: failed to parse \`matrix\` input as JSON: ${(e as Error).message}`);
|
||||
}
|
||||
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
||||
throw new Error('check-config: `matrix` must be a JSON object');
|
||||
}
|
||||
const include = (parsed as Record<string, unknown>).include;
|
||||
if (!Array.isArray(include)) {
|
||||
throw new Error('check-config: `matrix.include` must be an array');
|
||||
}
|
||||
return parsed as Matrix;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* A smoke-test probe the check-store workflow can run against a
|
||||
* running store. `page` does a GET / and asserts a non-empty title;
|
||||
* `graphql` POSTs a storeConfig query to /graphql. Probes are opt-in
|
||||
* per job because not every edition exposes every surface (e.g. the
|
||||
* mage-os minimal edition ships no GraphQL modules, so /graphql 404s).
|
||||
*/
|
||||
export const PROBES = ['page', 'graphql'] as const;
|
||||
|
||||
export type Probe = (typeof PROBES)[number];
|
||||
|
||||
export const isProbe = (value: unknown): value is Probe =>
|
||||
typeof value === 'string' && (PROBES as readonly string[]).includes(value);
|
||||
@@ -0,0 +1,39 @@
|
||||
import { resolveConfig } from './resolve';
|
||||
import { Matrix } from './types';
|
||||
|
||||
const MATRIX: Matrix = {
|
||||
include: [{
|
||||
php: '8.3',
|
||||
services: {
|
||||
mysql: { image: 'mysql:8' },
|
||||
opensearch: { image: 'opensearchproject/opensearch:2' },
|
||||
rabbitmq: { image: 'rabbitmq:3' },
|
||||
valkey: { image: 'valkey:8' },
|
||||
nginx: { image: 'nginx:1.27' },
|
||||
'php-fpm': { image: 'php:8.3-fpm' },
|
||||
},
|
||||
}],
|
||||
};
|
||||
|
||||
describe('resolveConfig', () => {
|
||||
it('routes kind=store to the store resolver', () => {
|
||||
const resolved = resolveConfig({ jobs: { 'smoke-test': false } }, 'store', MATRIX);
|
||||
expect(resolved['smoke-test'].enabled).toBe(false);
|
||||
expect(resolved['unit-test'].enabled).toBe(true);
|
||||
});
|
||||
|
||||
it('routes kind=extension to the extension resolver', () => {
|
||||
const resolved = resolveConfig({ jobs: { 'compile-extension': false } }, 'extension', MATRIX);
|
||||
expect(resolved['compile-extension'].enabled).toBe(false);
|
||||
expect(resolved['integration_test'].enabled).toBe(true);
|
||||
});
|
||||
|
||||
it('rejects a job name from the other kind', () => {
|
||||
expect(() => resolveConfig({ jobs: { 'smoke-test': false } }, 'extension', MATRIX)).toThrowError(
|
||||
/unknown job "smoke-test" for kind "extension"/
|
||||
);
|
||||
expect(() => resolveConfig({ jobs: { 'unit-test-extension': false } }, 'store', MATRIX)).toThrowError(
|
||||
/unknown job "unit-test-extension" for kind "store"/
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Kind, Matrix, RawConfig, ResolvedConfig } from './types';
|
||||
import { resolveStoreConfig } from './kinds/store';
|
||||
import { resolveExtensionConfig } from './kinds/extension';
|
||||
|
||||
/**
|
||||
* Dispatches to the per-kind resolver. Each kind owns its own list
|
||||
* of jobs and per-job defaults; this function just routes the call
|
||||
* and forwards the supported-version matrix.
|
||||
*/
|
||||
export const resolveConfig = (raw: RawConfig, kind: Kind, matrix: Matrix): ResolvedConfig => {
|
||||
if (kind === 'store') return resolveStoreConfig(raw, matrix);
|
||||
return resolveExtensionConfig(raw, matrix);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { isTier, servicesForTiers, TIER_TO_SERVICES } from './tier-map';
|
||||
|
||||
describe('isTier', () => {
|
||||
it('accepts every key in TIER_TO_SERVICES', () => {
|
||||
for (const tier of Object.keys(TIER_TO_SERVICES)) {
|
||||
expect(isTier(tier)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
it('rejects unknown strings', () => {
|
||||
expect(isTier('llm')).toBe(false);
|
||||
expect(isTier('')).toBe(false);
|
||||
});
|
||||
|
||||
it('rejects non-strings', () => {
|
||||
expect(isTier(42)).toBe(false);
|
||||
expect(isTier(null)).toBe(false);
|
||||
expect(isTier(undefined)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('servicesForTiers', () => {
|
||||
it('returns an empty set for an empty tier list', () => {
|
||||
expect([...servicesForTiers([])]).toEqual([]);
|
||||
});
|
||||
|
||||
it('expands a single tier to its concrete service names', () => {
|
||||
expect([...servicesForTiers(['queue'])]).toEqual(['rabbitmq']);
|
||||
});
|
||||
|
||||
it('expands the search tier to both implementations', () => {
|
||||
expect([...servicesForTiers(['search'])].sort()).toEqual(['elasticsearch', 'opensearch']);
|
||||
});
|
||||
|
||||
it('expands the web tier to nginx + php-fpm', () => {
|
||||
expect([...servicesForTiers(['web'])].sort()).toEqual(['nginx', 'php-fpm']);
|
||||
});
|
||||
|
||||
it('unions across multiple tiers', () => {
|
||||
expect([...servicesForTiers(['cache', 'queue'])].sort()).toEqual(['rabbitmq', 'redis', 'valkey']);
|
||||
});
|
||||
|
||||
it('deduplicates if the same tier appears twice', () => {
|
||||
expect([...servicesForTiers(['queue', 'queue'])]).toEqual(['rabbitmq']);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* A category of services that can be selected for a job. Mirrors the
|
||||
* `Tier` concept in `supported-version` but adds the `web` tier so the
|
||||
* smoke-test and integration jobs can opt the nginx + php-fpm pair in
|
||||
* or out as a unit. Intentionally narrower than supported-version's
|
||||
* tier set: this file only names tiers that the resolve-check-config
|
||||
* schema lets callers toggle.
|
||||
*/
|
||||
export type Tier = 'db' | 'search' | 'queue' | 'cache' | 'web';
|
||||
|
||||
/**
|
||||
* Expansion of each tier to the concrete service names that may
|
||||
* appear in a supported-version matrix entry's `services` map.
|
||||
* Filtering a matrix entry's services for a tier list means keeping
|
||||
* the keys that union to the values of the selected tiers here.
|
||||
*/
|
||||
export const TIER_TO_SERVICES: Record<Tier, readonly string[]> = {
|
||||
db: ['mysql'],
|
||||
search: ['opensearch', 'elasticsearch'],
|
||||
queue: ['rabbitmq'],
|
||||
cache: ['valkey', 'redis'],
|
||||
web: ['nginx', 'php-fpm'],
|
||||
};
|
||||
|
||||
export const isTier = (value: unknown): value is Tier =>
|
||||
typeof value === 'string' && value in TIER_TO_SERVICES;
|
||||
|
||||
/**
|
||||
* Returns the flat set of concrete service names for a list of tiers.
|
||||
* Used to filter a matrix entry's `services` map down to only the
|
||||
* containers a particular job actually needs.
|
||||
*/
|
||||
export const servicesForTiers = (tiers: readonly Tier[]): Set<string> => {
|
||||
const result = new Set<string>();
|
||||
for (const tier of tiers) {
|
||||
for (const name of TIER_TO_SERVICES[tier]) result.add(name);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
import { Tier } from './tier-map';
|
||||
import { Probe } from './probe';
|
||||
|
||||
/**
|
||||
* Which reusable workflow a config belongs to. Selects the known-job
|
||||
* list used for validation and the default config path.
|
||||
*/
|
||||
export type Kind = 'store' | 'extension';
|
||||
|
||||
/**
|
||||
* A single service container definition from supported-version's
|
||||
* matrix output. We don't model the inner shape here — we just
|
||||
* preserve unknown keys when filtering.
|
||||
*/
|
||||
export interface ServiceConfig {
|
||||
image: string;
|
||||
env?: Record<string, string>;
|
||||
ports?: string[];
|
||||
options?: string;
|
||||
volumes?: string[];
|
||||
}
|
||||
|
||||
export interface Services {
|
||||
[serviceName: string]: ServiceConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* One row of supported-version's matrix. Carries the PHP/Composer/etc
|
||||
* coordinates plus the concrete `services` map this job should bring
|
||||
* up. We type the known fields supported-version emits and allow
|
||||
* extras to pass through untouched.
|
||||
*/
|
||||
export interface MatrixEntry {
|
||||
services?: Services;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* The matrix shape emitted by supported-version, suitable for
|
||||
* `strategy.matrix` in GitHub Actions.
|
||||
*/
|
||||
export interface Matrix {
|
||||
include: MatrixEntry[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-job static defaults declared by each kind module.
|
||||
*
|
||||
* `services` is the tier list used when the caller's config does not
|
||||
* override it — these tiers are user-toggleable through the schema.
|
||||
*
|
||||
* `requiredServices` is always merged in on top of the resolved list,
|
||||
* regardless of caller overrides. Use it for tiers a job structurally
|
||||
* cannot run without (e.g. mysql for a running store smoke-test) and
|
||||
* which therefore should not appear in the user-facing schema enum.
|
||||
*
|
||||
* `probes` is the default smoke-test probe list used when the caller
|
||||
* does not override it. Only jobs that declare it support the
|
||||
* `probes` config key; omit it for jobs that have no probe concept.
|
||||
*/
|
||||
export interface JobDefaults {
|
||||
services: readonly Tier[];
|
||||
requiredServices?: readonly Tier[];
|
||||
probes?: readonly Probe[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolved per-job output. `enabled` mirrors the input boolean (or
|
||||
* `enabled` key); `matrix` is supported-version's matrix with each
|
||||
* entry's `services` filtered to the tiers this job needs.
|
||||
*/
|
||||
export interface ResolvedJobConfig {
|
||||
enabled: boolean;
|
||||
matrix: Matrix;
|
||||
probes?: Probe[];
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map of job-name -> resolved config. Keys are exactly the job names
|
||||
* declared by the kind module (omitted-by-caller jobs still appear,
|
||||
* carrying defaults so the consumer's `if:` guard works uniformly).
|
||||
*/
|
||||
export interface ResolvedConfig {
|
||||
[jobName: string]: ResolvedJobConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shape of a single per-job entry in the user's JSON config file.
|
||||
* - `true` / `false`: shorthand for `{ enabled: true|false }`
|
||||
* - object: explicit enabled flag plus an optional tier list under
|
||||
* `services` and an optional probe list under `probes` (both
|
||||
* validated against the per-kind schema).
|
||||
*/
|
||||
export type RawJobConfig =
|
||||
| boolean
|
||||
| { enabled?: boolean; services?: string[]; probes?: string[]; [key: string]: unknown };
|
||||
|
||||
/**
|
||||
* Top-level shape of the user's JSON config file. Job toggles live
|
||||
* under `jobs`; the rest of the top level is reserved for future
|
||||
* global keys.
|
||||
*/
|
||||
export interface RawConfig {
|
||||
jobs?: { [jobName: string]: RawJobConfig };
|
||||
[key: string]: unknown;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true,
|
||||
"esModuleInterop": true,
|
||||
"typeRoots": ["../node_modules/@types"],
|
||||
"types": ["jest"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# Sansec eComscan Security Scan Action
|
||||
|
||||
A Github Action that runs the [Sansec eComscan](https://sansec.io/ecomscan) security scanner.
|
||||
|
||||
## Inputs
|
||||
|
||||
See the [action.yml](./action.yml)
|
||||
|
||||
## Usage
|
||||
|
||||
The caller is responsible for checking out the repository before calling this action. A valid Sansec license key must be passed via the `ecomscan_key` input.
|
||||
|
||||
The `path` input should point to the root of the Magento installation — the directory that contains `app/`, `vendor/`, etc. It defaults to `.` (the current working directory).
|
||||
|
||||
```yml
|
||||
name: Sansec eComscan Security Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request_target:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
run-ecomscan:
|
||||
# Skip if it's a push event on a PR (it can't access secrets)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/sansec-ecomscan@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
license: ${{ secrets.SANSEC_LICENSE_KEY }}
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
name: "Sansec eComscan Security Scan"
|
||||
author: "Graycore"
|
||||
description: "A Github Action that runs the Sansec eComscan security scanner."
|
||||
|
||||
inputs:
|
||||
license:
|
||||
required: true
|
||||
description: "Sansec license key (ECOMSCAN_KEY)"
|
||||
|
||||
path:
|
||||
required: true
|
||||
default: '.'
|
||||
description: "The directory to scan."
|
||||
|
||||
skip_database:
|
||||
required: false
|
||||
default: 'true'
|
||||
description: "Skip the database scan (--skip-database). Defaults to true."
|
||||
|
||||
skip-server-checks:
|
||||
required: false
|
||||
default: 'true'
|
||||
description: "Skip server / os level checks like copy-fail"
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Download eComscan
|
||||
shell: bash
|
||||
run: wget https://ecomscan.com/downloads/linux-amd64/ecomscan
|
||||
|
||||
- name: Fix permissions
|
||||
shell: bash
|
||||
run: chmod +x ecomscan
|
||||
|
||||
- name: Run eComscan
|
||||
shell: bash
|
||||
env:
|
||||
ECOMSCAN_KEY: ${{ inputs.license }}
|
||||
run: |
|
||||
[ "${{ inputs.skip-server-checks }}" = "true" ] && export ECOMSCAN_SKIP_SERVER_CHECKS=true
|
||||
FLAGS=(--no-auto-update --deep --format=csv)
|
||||
[ "${{ inputs.skip_database }}" = "true" ] && FLAGS+=(--skip-database)
|
||||
output=$(./ecomscan "${FLAGS[@]}" "${{ inputs.path }}")
|
||||
if [ -n "$output" ]; then
|
||||
echo "Security issues found:"
|
||||
echo "$output"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
branding:
|
||||
icon: "shield"
|
||||
color: "red"
|
||||
@@ -30,8 +30,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: A job to semantically compare two versions
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: graycoreio/github-actions-magento2/semver-compare@main
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/semver-compare@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
version: 2.1.0
|
||||
compare_against: 2.2.3
|
||||
|
||||
+42
-13
@@ -1,29 +1,58 @@
|
||||
# Magento 2 setup:di:compile action
|
||||
A Github Action that runs `php bin/magento setup:di:compile` and checks for compilation errors.
|
||||
# Setup DI Compile
|
||||
|
||||
A GitHub Action that enables all Magento modules and runs `bin/magento setup:di:compile`.
|
||||
|
||||
The caller is responsible for checkout, PHP/composer setup, and `composer install`. This action only performs the compilation step.
|
||||
|
||||
## Inputs
|
||||
|
||||
See the [action.yml](./action.yml)
|
||||
| Input | Required | Default | Description |
|
||||
| ------ | -------- | ------- | ------------------------------------------------------------------ |
|
||||
| `path` | No | `.` | Path to the Magento root directory. |
|
||||
|
||||
## Usage
|
||||
|
||||
```yml
|
||||
name: Magento setup:di:compile check
|
||||
name: DI Compile
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
setup-di-compile:
|
||||
compute_matrix:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
matrix: ${{ steps.supported-version.outputs.matrix }}
|
||||
steps:
|
||||
- uses: graycoreio/github-actions-magento2/setup-di-compile@main
|
||||
with:
|
||||
php_version: "8.3"
|
||||
composer_version: "2"
|
||||
- uses: actions/checkout@v6
|
||||
- uses: graycoreio/github-actions-magento2/supported-version@v8.5.0 # x-release-please-version
|
||||
id: supported-version
|
||||
|
||||
compile:
|
||||
needs: compute_matrix
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/setup-magento@v8.5.0 # x-release-please-version
|
||||
id: setup-magento
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
tools: composer:v${{ matrix.composer }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@v8.5.0 # x-release-please-version
|
||||
|
||||
- run: composer install
|
||||
env:
|
||||
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/setup-di-compile@v8.5.0 # x-release-please-version
|
||||
with:
|
||||
path: ${{ steps.setup-magento.outputs.path }}
|
||||
```
|
||||
|
||||
+12
-44
@@ -1,58 +1,26 @@
|
||||
name: "Magento compilation (setup:di:compile)"
|
||||
author: "MageOS"
|
||||
description: "A Github Action that runs bin/magento setup:di:compile."
|
||||
author: "Graycore"
|
||||
description: "A GitHub Action that runs bin/magento setup:di:compile."
|
||||
|
||||
inputs:
|
||||
php_version:
|
||||
required: true
|
||||
default: "8.3"
|
||||
description: "PHP version used to run setup:di:compile."
|
||||
|
||||
composer_version:
|
||||
required: true
|
||||
default: "2"
|
||||
description: "The version of composer to use."
|
||||
path:
|
||||
required: false
|
||||
default: "."
|
||||
description: "Path to the Magento root directory. Accepts the output of the setup-magento action."
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: Checkout Project
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Get changed files that could break compilation
|
||||
uses: tj-actions/changed-files@v39
|
||||
id: changed-files
|
||||
with:
|
||||
files_yaml: |
|
||||
magento:
|
||||
- 'composer.lock'
|
||||
- 'composer.json'
|
||||
- '**/*.php'
|
||||
- '**/*.xml'
|
||||
|
||||
- name: Set PHP Version
|
||||
if: steps.changed-files.outputs.magento_any_changed == 'true'
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ inputs.php_version }}
|
||||
tools: composer:v${{ inputs.composer_version }}
|
||||
coverage: none
|
||||
|
||||
- uses: graycoreio/github-actions-magento2/cache-magento@main
|
||||
with:
|
||||
mode: 'store'
|
||||
|
||||
- name: Install composer dependencies
|
||||
if: steps.changed-files.outputs.magento_any_changed == 'true'
|
||||
shell: bash
|
||||
run: composer install
|
||||
|
||||
- name: Enable all modules
|
||||
if: steps.changed-files.outputs.magento_any_changed == 'true'
|
||||
working-directory: ${{ inputs.path }}
|
||||
shell: bash
|
||||
run: php bin/magento module:enable --all
|
||||
|
||||
- name: Compile
|
||||
if: steps.changed-files.outputs.magento_any_changed == 'true'
|
||||
working-directory: ${{ inputs.path }}
|
||||
shell: bash
|
||||
run: php bin/magento setup:di:compile
|
||||
|
||||
branding:
|
||||
icon: "tool"
|
||||
color: "orange"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user