├── .eslintrc.cjs ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── documentation.md │ ├── feature_request.md │ ├── other.md │ └── performance_issue.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── _internal-coding-standard.yaml │ ├── _internal-get-composer-version.yaml │ ├── _internal-get-magento-version.yaml │ ├── _internal-install.yaml │ ├── _internal-integration.yaml │ ├── _internal-semver-compare.yaml │ ├── _internal-setup-magento.yaml │ ├── _internal-unit.yaml │ ├── _internal_test_actions.yaml │ ├── full-integration-tests.yaml │ ├── integration-README.md │ ├── integration.yaml │ ├── nx-integration-tests.yml │ ├── release-please.yml │ └── sansec-ecomscan.yml ├── .gitignore ├── .nvmrc ├── .release-please-manifest.json ├── .vscode └── extensions.json ├── CHANGELOG.md ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── README.md ├── _test └── demo-package │ ├── .gitignore │ ├── README.md │ ├── Test │ ├── Integration │ │ └── ItWorksTest.php │ └── Unit │ │ └── ItWorksTest.php │ ├── composer.json │ ├── composer.lock │ ├── etc │ └── module.xml │ ├── phpunit.xml │ └── registration.php ├── cache-magento ├── README.md └── action.yml ├── coding-standard-baseline ├── README.md └── action.yml ├── coding-standard ├── README.md └── action.yml ├── fix-magento-install ├── README.md └── action.yml ├── get-composer-version ├── README.md └── action.yml ├── get-magento-version ├── README.md └── action.yml ├── installation-test ├── README.md └── action.yml ├── nx-integration-tests-setup └── action.yml ├── package-lock.json ├── package.json ├── release-please-config.json ├── semver-compare ├── README.md └── action.yml ├── setup-di-compile ├── README.md └── action.yml ├── setup-magento ├── README.md └── action.yml ├── supported-services-matrix-calculator └── action.yml ├── supported-version ├── README.md ├── action.yml ├── dist │ └── index.js ├── jest.config.js ├── package-lock.json ├── package.json ├── src │ ├── index.ts │ ├── kind │ │ ├── get-currently-supported.spec.ts │ │ ├── get-currently-supported.ts │ │ ├── kinds.ts │ │ ├── special-versions │ │ │ ├── latest.json │ │ │ └── nightly.json │ │ ├── validate-kinds.spec.ts │ │ ├── validate-kinds.ts │ │ ├── validations │ │ │ ├── custom-versions-validator.ts │ │ │ └── is-known-kind.ts │ │ └── validator.ts │ ├── matrix │ │ ├── get-matrix-for-kind.spec.ts │ │ ├── get-matrix-for-kind.ts │ │ ├── get-matrix-for-versions.ts │ │ └── matrix-type.ts │ ├── nightly │ │ ├── amend-matrix-for-next.spec.ts │ │ ├── amend-matrix-for-next.ts │ │ ├── get-day-before.ts │ │ ├── get-next-version.spec.ts │ │ ├── get-next-version.ts │ │ ├── repository.ts │ │ ├── unify-next-package-name.spec.ts │ │ └── unify-next-package-name.ts │ ├── project │ │ ├── projects.ts │ │ ├── validate-projects.spec.ts │ │ ├── validate-projects.ts │ │ ├── validations │ │ │ ├── is-known-project.spec.ts │ │ │ └── is-known-project.ts │ │ └── validator.ts │ └── versions │ │ ├── get-versions-for-project.spec.ts │ │ ├── get-versions-for-project.ts │ │ ├── mage-os │ │ ├── composite.json │ │ └── individual.json │ │ └── magento-open-source │ │ ├── composite.json │ │ └── individual.json └── tsconfig.json ├── unit-test ├── README.md └── action.yml └── warden ├── integration-tests └── action.yml └── setup-environment └── action.yml /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended'], 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint'], 5 | root: true, 6 | }; -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report or Regression 3 | about: Create a report to help us fix an issue or regression 4 | title: '[BUG]' 5 | labels: 'bug' 6 | assignees: 'damienwebdev' 7 | --- 8 | 9 | 14 | 15 | # :bug: Bug report 16 | 17 | ## Current Behavior 18 | 19 | 20 | 21 | ## Expected Behavior 22 | 23 | 24 | 25 | ## Minimal reproduction of the problem with instructions 26 | 27 | 28 | 29 | ## What is the motivation / use case for changing the behavior? 30 | 31 | 32 | 33 | ## Environment 34 | 35 |

36 | Magento version: X.Y.Z 
37 | PHP Version version: X.Y.Z 
38 | 
39 | 
40 | Others:
41 | 
42 | 
-------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Documentation Request 3 | about: Request additional documentation or clarification on a feature. 4 | title: '[DOCS]' 5 | labels: 'docs' 6 | assignees: 'damienwebdev' 7 | --- 8 | 9 | 14 | 15 | # :page_facing_up: Documentation Request 16 | 17 | ## What were you doing? 18 | 19 | 20 | 21 | ## Expected behavior 22 | 23 | 24 | 25 | ## Existing Documentation 26 | 27 | 28 | ## Environment 29 | 30 |

31 | Magento version: X.Y.Z 
32 | PHP Version version: X.Y.Z 
33 | 
34 | 
35 | Others:
36 | 
37 | 
-------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Ask for a new feature, or something that you'd like to see changed. 4 | title: '[FEAT]' 5 | labels: 'feat' 6 | assignees: 'damienwebdev' 7 | --- 8 | 9 | 14 | 15 | # :bulb: Feature request 16 | 17 | ## Feature Name 18 | 19 | 20 | 21 | ## The Desired Behavior 22 | 23 | 24 | 25 | ## Your Use Case 26 | 27 | 28 | 29 | ## Prior Work 30 | 31 | 32 | 33 | ## Environment 34 | 35 |

36 | Magento version: X.Y.Z 
37 | PHP Version version: X.Y.Z 
38 | 
39 | 
40 | Others:
41 | 
42 | 
-------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/other.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Other 3 | about: Report a general issue that isn't covered by other issue templates. 4 | title: '[OTHER]' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | 14 | 15 | # :question: Other 16 | 17 | 18 | 19 | ## Environment 20 | 21 |

22 | Magento version: X.Y.Z 
23 | PHP Version version: X.Y.Z 
24 | 
25 | 
26 | Others:
27 | 
28 | 
-------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/performance_issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Performance Issue 3 | about: Create a report about a performance problem. 4 | title: '[PERF]' 5 | labels: 'perf' 6 | assignees: 'damienwebdev' 7 | --- 8 | 9 | 14 | 15 | # :turtle: Performance Issue 16 | 17 | ## Current behavior 18 | 19 | 20 | 21 | ## Expected behavior 22 | 23 | 24 | 25 | ## Minimal reproduction of the problem with instructions 26 | 27 | 28 | 29 | ## What is the motivation / use case for changing the behavior? 30 | 31 | 32 | 33 | ## Environment 34 | 35 |

36 | Magento version: X.Y.Z 
37 | PHP Version version: X.Y.Z 
38 | 
39 | 
40 | Others:
41 | 
42 | 
-------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## PR Checklist 2 | Please check if your PR fulfills the following requirements: 3 | 4 | - [ ] The commit message follows our guidelines: https://github.com/mage-os/github-actions/blob/main/CONTRIBUTING.md#commit 5 | - [ ] Tests for the changes have been added (for bug fixes / features) 6 | - [ ] Docs have been added / updated (for bug fixes / features) 7 | 8 | 9 | ## PR Type 10 | What kind of change does this PR introduce? 11 | 12 | 13 | - [ ] Bugfix 14 | - [ ] Feature 15 | - [ ] Code style update (formatting, local variables) 16 | - [ ] Refactoring (no functional changes, no api changes) 17 | - [ ] Build related changes 18 | - [ ] CI related changes 19 | - [ ] Documentation content changes 20 | - [ ] Other... Please describe: 21 | 22 | ## What is the current behavior? 23 | 24 | 25 | Fixes: N/A 26 | 27 | 28 | ## What is the new behavior? 29 | 30 | 31 | ## Does this PR introduce a breaking change? 32 | - [ ] Yes 33 | - [ ] No 34 | 35 | 36 | 37 | 38 | ## Other information 39 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Maintain dependencies for GitHub Actions 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "weekly" -------------------------------------------------------------------------------- /.github/workflows/_internal-coding-standard.yaml: -------------------------------------------------------------------------------- 1 | name: Coding Standard 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "_test/demo-package/**" 9 | - ".github/workflows/_internal-coding-standard.yaml" 10 | - "coding-standard/**" 11 | - "!(**/*.md)" 12 | pull_request: 13 | branches: 14 | - main 15 | paths: 16 | - "_test/demo-package/**" 17 | - ".github/workflows/_internal-coding-standard.yaml" 18 | - "coding-standard/**" 19 | - "!(**/*.md)" 20 | workflow_dispatch: 21 | inputs: 22 | version: 23 | type: string 24 | default: '*' 25 | description: The version of the coding standard to use. 26 | required: false 27 | path: 28 | type: string 29 | default: '_test/demo-package' 30 | description: Path to run the coding standard on. 31 | required: true 32 | 33 | jobs: 34 | compute_matrix: 35 | runs-on: ubuntu-latest 36 | outputs: 37 | matrix: ${{ steps.supported-version.outputs.matrix }} 38 | steps: 39 | - uses: actions/checkout@v4 40 | - uses: ./supported-version 41 | with: 42 | kind: all 43 | id: supported-version 44 | - run: echo ${{ steps.supported-version.outputs.matrix }} 45 | 46 | coding-standard: 47 | needs: compute_matrix 48 | strategy: 49 | matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }} 50 | fail-fast: false 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v4 54 | - uses: './coding-standard' 55 | with: 56 | version: ${{ github.event.inputs.version || '*' }} 57 | path: ${{ github.event.inputs.path || '_test/demo-package' }} 58 | composer_version: ${{ matrix.composer }} 59 | php_version: ${{ matrix.php }} -------------------------------------------------------------------------------- /.github/workflows/_internal-get-composer-version.yaml: -------------------------------------------------------------------------------- 1 | name: Get Composer Version 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | - testing 8 | paths: 9 | - ".github/workflows/_internal-get-composer-version.yaml" 10 | - "get-composer-version/**" 11 | - "!(**/*.md)" 12 | pull_request: 13 | branches: 14 | - main 15 | paths: 16 | - ".github/workflows/_internal-get-composer-version.yaml" 17 | - "get-composer-version/**" 18 | - "!(**/*.md)" 19 | 20 | jobs: 21 | get-composer-version: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v4 25 | - name: Set PHP Version 26 | uses: shivammathur/setup-php@v2 27 | with: 28 | php-version: 8.3 29 | tools: composer:v2.8.4 30 | 31 | - uses: ./get-composer-version 32 | id: composer-version 33 | 34 | 35 | - name: Fail if versions do not match 36 | if: steps.composer-version.outputs.version != '2.8.4' 37 | shell: bash 38 | run: echo "${{ steps.composer-version.outputs.version }}" && exit 1 39 | -------------------------------------------------------------------------------- /.github/workflows/_internal-get-magento-version.yaml: -------------------------------------------------------------------------------- 1 | name: Get Magento Version 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - ".github/workflows/_internal-get-magento-version.yaml" 9 | - "get-magento-version/**" 10 | - "!(**/*.md)" 11 | pull_request: 12 | branches: 13 | - main 14 | paths: 15 | - ".github/workflows/_internal-get-magento-version.yaml" 16 | - "get-magento-version/**" 17 | - "!(**/*.md)" 18 | 19 | jobs: 20 | get-magento-version: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | - name: Set PHP Version 25 | uses: shivammathur/setup-php@v2 26 | with: 27 | php-version: 8.3 28 | tools: composer:v2.8.4 29 | 30 | - run: composer create-project --repository-url="https://mirror.mage-os.org" "magento/project-community-edition:2.4.7-p4" ../magento2 --no-install 31 | shell: bash 32 | name: Create Magento ${{ matrix.magento }} Project 33 | 34 | - uses: ./get-magento-version 35 | id: magento-version 36 | with: 37 | working-directory: ../magento2 38 | 39 | - name: Fail if key does not match 40 | if: steps.magento-version.outputs.version != '"2.4.7-p4"' 41 | shell: bash 42 | run: echo "${{ steps.magento-version.outputs.version }}" && exit 1 43 | -------------------------------------------------------------------------------- /.github/workflows/_internal-install.yaml: -------------------------------------------------------------------------------- 1 | name: Installation Test 2 | 3 | on: 4 | workflow_dispatch: {} 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - "_test/demo-package/**" 10 | - "installation-test/**" 11 | - ".github/workflows/_internal-install.yaml" 12 | - "supported-version/**" 13 | - "!(**/*.md)" 14 | pull_request: 15 | branches: 16 | - main 17 | paths: 18 | - "_test/demo-package/**" 19 | - "installation-test/**" 20 | - ".github/workflows/_internal-install.yaml" 21 | - "supported-version/**" 22 | - "!(**/*.md)" 23 | 24 | jobs: 25 | compute_matrix: 26 | runs-on: ubuntu-latest 27 | outputs: 28 | matrix: ${{ steps.supported-version.outputs.matrix }} 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: ./supported-version 32 | with: 33 | kind: all 34 | id: supported-version 35 | - run: echo ${{ steps.supported-version.outputs.matrix }} 36 | 37 | install-test: 38 | needs: compute_matrix 39 | strategy: 40 | matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }} 41 | fail-fast: false 42 | runs-on: ubuntu-latest 43 | steps: 44 | - uses: actions/checkout@v4 45 | - uses: ./installation-test 46 | with: 47 | composer_version: ${{ matrix.composer }} 48 | php_version: ${{ matrix.php }} 49 | magento_version: ${{ matrix.magento }} 50 | package_name: mage-os/magento2-demo-package 51 | source_folder: $GITHUB_WORKSPACE/_test/demo-package 52 | -------------------------------------------------------------------------------- /.github/workflows/_internal-integration.yaml: -------------------------------------------------------------------------------- 1 | name: Integration Test 2 | 3 | on: 4 | workflow_dispatch: {} 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - "_test/demo-package/**" 10 | - ".github/workflows/_internal-integration.yaml" 11 | - ".github/workflows/integration.yaml" 12 | - "supported-version/**" 13 | - "!(**/*.md)" 14 | pull_request: 15 | branches: 16 | - main 17 | paths: 18 | - "_test/demo-package/**" 19 | - ".github/workflows/_internal-integration.yaml" 20 | - ".github/workflows/integration.yaml" 21 | - "supported-version/**" 22 | - "!(**/*.md)" 23 | 24 | jobs: 25 | compute_matrix: 26 | runs-on: ubuntu-latest 27 | outputs: 28 | matrix: ${{ steps.supported-version.outputs.matrix }} 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: ./supported-version 32 | with: 33 | kind: all 34 | id: supported-version 35 | - run: echo ${{ steps.supported-version.outputs.matrix }} 36 | integration-workflow: 37 | needs: compute_matrix 38 | uses: ./.github/workflows/integration.yaml 39 | with: 40 | package_name: mage-os/magento2-demo-package 41 | source_folder: $GITHUB_WORKSPACE/_test/demo-package 42 | matrix: ${{ needs.compute_matrix.outputs.matrix }} 43 | test_command: ../../../vendor/bin/phpunit ../../../vendor/mage-os/magento2-demo-package/Test/Integration 44 | fail-fast: false 45 | -------------------------------------------------------------------------------- /.github/workflows/_internal-semver-compare.yaml: -------------------------------------------------------------------------------- 1 | name: Test semvar-compare action 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - ".github/workflows/_internal-semver-compare.yaml" 9 | - "semver-compare/**" 10 | - "!(**/*.md)" 11 | pull_request: 12 | branches: 13 | - main 14 | paths: 15 | - ".github/workflows/_internal-semver-compare.yaml" 16 | - "semver-compare/**" 17 | - "!(**/*.md)" 18 | 19 | jobs: 20 | semver-compare: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: ./semver-compare 26 | id: version-compare-1 27 | with: 28 | version: 2.2.3 29 | compare_against: 2.3 30 | 31 | - uses: ./semver-compare 32 | id: version-compare-2 33 | with: 34 | version: 2 35 | compare_against: 2.0.1 36 | 37 | - uses: ./semver-compare 38 | id: version-compare-3 39 | with: 40 | version: 2.2.1 41 | compare_against: 2.2 42 | 43 | 44 | - uses: ./semver-compare 45 | id: version-compare-4 46 | with: 47 | version: 2.2.0 48 | compare_against: 2.2.0 49 | 50 | - name: Fail if 2.3 is not higher than 2.2.3 51 | if: steps.version-compare-1.outputs.result != -1 52 | shell: bash 53 | run: echo "FAIL because 2.3 must be higher than 2.2.3 Compare 2.2.3 to 2.3 renders ${{ steps.version-compare-1.outputs.result }}" && exit 1 54 | 55 | 56 | - name: Fail if 2.0.1 is not higher than 2 57 | if: steps.version-compare-2.outputs.result != -1 58 | shell: bash 59 | run: echo "FAIL because 2.0.1 must be higher than 2 Compare 2 to 2.0.1 renders ${{ steps.version-compare-2.outputs.result }}" && exit 1 60 | 61 | - name: Fail if 2.2.1 is not higher than 2.2 62 | if: steps.version-compare-3.outputs.result != 1 63 | shell: bash 64 | run: echo "FAIL because 2.2.1 must be higher than 2.2 Compare 2.2.1 to 2.2 renders ${{ steps.version-compare-3.outputs.result }}" && exit 1 65 | 66 | - name: Fail if 2.2.0 is not equals to 2.2.0 67 | if: steps.version-compare-4.outputs.result != 0 68 | shell: bash 69 | run: echo "FAIL because 2.2.0 must be equal to 2.2.0 Compare 2.2.0 to 2.2.0 renders ${{ steps.version-compare-4.outputs.result }}" && exit 1 70 | -------------------------------------------------------------------------------- /.github/workflows/_internal-setup-magento.yaml: -------------------------------------------------------------------------------- 1 | name: Setup Magento Test 2 | 3 | on: 4 | workflow_dispatch: {} 5 | push: 6 | branches: 7 | - main 8 | paths: 9 | - "setup-magento/**" 10 | - ".github/workflows/_internal-setup-magento.yaml" 11 | - "supported-version/**" 12 | - "!(**/*.md)" 13 | pull_request: 14 | branches: 15 | - main 16 | paths: 17 | - "setup-magento/**" 18 | - ".github/workflows/_internal-setup-magento.yaml" 19 | - "supported-version/**" 20 | - "!(**/*.md)" 21 | 22 | env: 23 | PSEUDO_REPO_FOLDER: ../magento_repo 24 | magento_folder: ../magento2 25 | 26 | jobs: 27 | compute_matrix: 28 | runs-on: ubuntu-latest 29 | outputs: 30 | matrix: ${{ steps.supported-version.outputs.matrix }} 31 | steps: 32 | - uses: actions/checkout@v4 33 | - uses: ./supported-version 34 | with: 35 | kind: currently-supported 36 | id: supported-version 37 | - run: echo ${{ steps.supported-version.outputs.matrix }} 38 | 39 | setup-magento-store: 40 | needs: compute_matrix 41 | strategy: 42 | matrix: ${{ fromJSON(needs.compute_matrix.outputs.matrix) }} 43 | fail-fast: false 44 | runs-on: ubuntu-latest 45 | steps: 46 | - uses: actions/checkout@v4 47 | 48 | - run: | 49 | PSEUDO_STORE_FULL_PATH=$(realpath "${{ env.PSEUDO_REPO_FOLDER }}") 50 | echo "PSEUDO_STORE_FULL_PATH=$PSEUDO_STORE_FULL_PATH" >> $GITHUB_ENV 51 | name: Generate Full Pseudo Store Path 52 | shell: bash 53 | 54 | - name: Set PHP Version 55 | uses: shivammathur/setup-php@v2 56 | with: 57 | php-version: ${{ matrix.php }} 58 | tools: composer:v${{ matrix.composer }} 59 | 60 | - uses: actions/cache@v4 61 | id: setup-magento-store-cache 62 | with: 63 | key: setup-magento-ci | ${{ runner.os }} | ${{ matrix.magento }} 64 | path: ${{ env.PSEUDO_STORE_FULL_PATH }} 65 | 66 | - run: composer create-project --repository-url="https://mirror.mage-os.org" "${{ matrix.magento }}" "${{ env.PSEUDO_REPO_FOLDER }}" --no-install 67 | name: Create Store to simulate a real Magento store in a real repo. 68 | if: steps.setup-magento-store-cache.outputs.cache-hit != 'true' 69 | 70 | - uses: ./fix-magento-install 71 | name: Fix Magento Out of Box Install Issues 72 | with: 73 | magento_directory: ${{ env.PSEUDO_REPO_FOLDER }} 74 | if: steps.setup-magento-store-cache.outputs.cache-hit != 'true' 75 | 76 | - run: composer install 77 | shell: bash 78 | working-directory: "${{ env.PSEUDO_REPO_FOLDER }}" 79 | if: steps.setup-magento-store-cache.outputs.cache-hit != 'true' 80 | 81 | - 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 82 | working-directory: "${{ env.PSEUDO_REPO_FOLDER }}" 83 | if: steps.setup-magento-store-cache.outputs.cache-hit != 'true' 84 | 85 | - run: cp -R ${{ env.PSEUDO_REPO_FOLDER }} ${{ env.magento_folder }} 86 | shell: bash 87 | 88 | - uses: ./setup-magento 89 | id: setup-magento 90 | with: 91 | php-version: ${{ matrix.php }} 92 | tools: composer:v${{ matrix.composer }} 93 | mode: store 94 | working-directory: ${{ env.magento_folder }} 95 | 96 | - uses: mage-os/github-actions/cache-magento@main 97 | with: 98 | mode: 'store' 99 | composer_cache_key: '${{ matrix.magento }}' 100 | 101 | - run: composer install 102 | name: Composer install 103 | shell: bash 104 | working-directory: ${{ steps.setup-magento.outputs.path }} 105 | 106 | setup-magento-extension: 107 | runs-on: ubuntu-latest 108 | steps: 109 | - uses: actions/checkout@v4 110 | 111 | - uses: ./setup-magento 112 | id: setup-magento 113 | with: 114 | php-version: 8.3 115 | tools: composer:v2 116 | mode: extension 117 | magento_version: magento/project-community-edition:2.4.7-p4 118 | 119 | - uses: mage-os/github-actions/cache-magento@main 120 | with: 121 | mode: 'extension' 122 | composer_cache_key: 'magento/project-community-edition:2.4.7-p4' 123 | 124 | - run: composer install 125 | name: Composer install 126 | shell: bash 127 | working-directory: ${{ steps.setup-magento.outputs.path }} 128 | -------------------------------------------------------------------------------- /.github/workflows/_internal-unit.yaml: -------------------------------------------------------------------------------- 1 | name: Unit Test 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - "_test/demo-package/**" 9 | - ".github/workflows/_internal-unit.yaml" 10 | - "unit-test/**" 11 | - "!(**/*.md)" 12 | pull_request: 13 | branches: 14 | - main 15 | paths: 16 | - "_test/demo-package/**" 17 | - ".github/workflows/_internal-unit.yaml" 18 | - "unit-test/**" 19 | - "!(**/*.md)" 20 | 21 | jobs: 22 | unit-test: 23 | strategy: 24 | matrix: 25 | php_version: 26 | - 8.2 27 | - 8.3 28 | runs-on: ubuntu-latest 29 | steps: 30 | - uses: actions/checkout@v4 31 | - uses: ./unit-test 32 | with: 33 | source_folder: _test/demo-package 34 | php_version: ${{ matrix.php_version }} 35 | -------------------------------------------------------------------------------- /.github/workflows/_internal_test_actions.yaml: -------------------------------------------------------------------------------- 1 | name: Test Actions 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - ".github/workflows/_internal-supported-version.yaml" 9 | - "supported-version/**" 10 | - "package-lock.json" 11 | - "!(**/*.md)" 12 | pull_request: 13 | branches: 14 | - main 15 | paths: 16 | - ".github/workflows/_internal-supported-version.yaml" 17 | - "supported-version/**" 18 | - "package-lock.json" 19 | - "!(**/*.md)" 20 | 21 | jobs: 22 | unit-test: 23 | runs-on: ubuntu-latest 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - run: npm ci 28 | shell: bash 29 | 30 | - run: npm test 31 | shell: bash -------------------------------------------------------------------------------- /.github/workflows/full-integration-tests.yaml: -------------------------------------------------------------------------------- 1 | ## Workflow is only for Magento 2 Main repo - app/code and dev/tests/integration are supported only 2 | ## 3rd party modules are not supported yet 3 | name: Integration Tests - Full Test Suite 4 | run-name: ${{ github.actor }} is running Full Integration Test Suite 5 | 6 | on: 7 | workflow_call: 8 | inputs: 9 | repository: 10 | type: string 11 | description: "Repository" 12 | required: true 13 | head: 14 | type: string 15 | description: "head SHA" 16 | required: true 17 | test_directory: 18 | type: string 19 | description: "Test directory to run integration tests" 20 | required: false 21 | 22 | permissions: 23 | contents: write 24 | 25 | jobs: 26 | matrix-calculator: 27 | runs-on: ubuntu-latest 28 | outputs: 29 | php_versions: ${{ steps.set-matrix.outputs.php_versions }} 30 | database_versions: ${{ steps.set-matrix.outputs.database_versions }} 31 | search_versions: ${{ steps.set-matrix.outputs.search_versions }} 32 | message_queue_versions: ${{ steps.set-matrix.outputs.message_queue_versions }} 33 | cache_versions: ${{ steps.set-matrix.outputs.cache_versions }} 34 | http_cache_versions: ${{ steps.set-matrix.outputs.http_cache_versions }} 35 | testsuite_dirs: ${{ steps.set-matrix-testsuite.outputs.testsuite_dirs }} 36 | steps: 37 | - name: Checkout commit 38 | uses: actions/checkout@v4 39 | with: 40 | repository: ${{ github.event.inputs.repository }} 41 | ref: ${{ github.event.inputs.head }} 42 | fetch-depth: 1 43 | 44 | - id: set-matrix 45 | name: Calculate Matrix 46 | run: | 47 | echo "php_versions=$(jq -c .services.php supported-services.json)" >> "$GITHUB_OUTPUT" 48 | echo "database_versions=$(jq -c .services.database supported-services.json)" >> "$GITHUB_OUTPUT" 49 | echo "search_versions=$(jq -c .services.search supported-services.json)" >> "$GITHUB_OUTPUT" 50 | echo "message_queue_versions=$(jq -c .services.message_queue supported-services.json)" >> "$GITHUB_OUTPUT" 51 | echo "cache_versions=$(jq -c .services.cache supported-services.json)" >> "$GITHUB_OUTPUT" 52 | echo "http_cache_versions=$(jq -c .services.http_cache supported-services.json)" >> "$GITHUB_OUTPUT" 53 | 54 | - id: set-matrix-testsuite 55 | name: Calculate Matrix for testsuite 56 | working-directory: dev/tests/integration 57 | run: | 58 | 59 | ### TODO: rebuild all that hell to node-js 60 | 61 | if [ -n "${{ github.event.inputs.test_directory }}" ]; then 62 | echo "testsuite_dirs=['${{ github.event.inputs.test_directory }}']" >> "$GITHUB_OUTPUT" 63 | exit 0 64 | fi 65 | 66 | OUTPUT_FILE="integration-testsuites.json" 67 | TESTSUITE_DIR="./testsuite/Magento" 68 | CODE_DIR="../../../app/code" 69 | MAX_DIRS_PER_LINE=1 70 | 71 | ## variable with array of exclusion list of directories - they will be handled separately and splitted on more batches 72 | EXCLUSION_LIST=("./testsuite/Magento/Catalog" "./testsuite/Magento/Bundle" "./testsuite/Magento/AsynchronousOperations" "./testsuite/Magento/Sales") 73 | 74 | ## variable with array of exclusion list of files - separate run will be executed for each file (separate place in tests matrix) 75 | STANDALONE_TESTS=("./testsuite/Magento/AsynchronousOperations/Model/MassScheduleTest.php" "./testsuite/Magento/Catalog/Observer/SwitchPriceAttributeScopeOnConfigChangeTest.php" "./testsuite/Magento/Catalog/Model/CategoryTest.php" "./testsuite/Magento/Bundle/Model/ProductTest.php" "./testsuite/Magento/Catalog/Block/Adminhtml/Category/Tab/ProductTest.php") 76 | 77 | # Initialize variables 78 | dir_count=0 79 | json_content="{\n\t\"testsuites\": [\n\t\t\"" 80 | current_line="" 81 | 82 | # Function to add a directory to the current line, handling comma and count 83 | add_dir_to_line() { 84 | local dir=$1 85 | # Check if current_line is empty to avoid leading commas 86 | if [ -z "$current_line" ]; then 87 | current_line="$dir" 88 | else 89 | current_line="$current_line,$dir" 90 | fi 91 | dir_count=$((dir_count + 1)) 92 | 93 | if [ "$dir_count" -eq "$MAX_DIRS_PER_LINE" ]; then 94 | json_content="$json_content$current_line" 95 | json_content="$json_content\",\n\t\t\"" 96 | current_line="" 97 | dir_count=0 98 | fi 99 | } 100 | 101 | # Iterate over the directories and populate the JSON content 102 | while IFS= read -r -d '' dir; do 103 | # if dir is in EXCLUSION_LIST then skip it 104 | if [[ " ${EXCLUSION_LIST[@]} " =~ " ${dir} " ]]; then 105 | continue 106 | fi 107 | add_dir_to_line "${dir}" 108 | done < <(find "$TESTSUITE_DIR" -mindepth 1 -maxdepth 1 -type d -print0) 109 | 110 | # Add app/code integration test directories 111 | while IFS= read -r -d '' dir; do 112 | relative_dir="${dir}" # Convert absolute path to relative 113 | add_dir_to_line "$relative_dir" 114 | done < <(find "$CODE_DIR" -mindepth 4 -maxdepth 4 -type d -name 'Integration' -print0) 115 | 116 | # Handle exclusion list 117 | # run over EXCLUSION_LIST, find all "*Test.php" files, and put them in array. Exclude directories. 118 | EXCLUSION_LIST_FILES=() 119 | for dir in "${EXCLUSION_LIST[@]}"; do 120 | while IFS= read -r -d '' file; do 121 | # check if file is in STANDALONE_TESTS 122 | if [[ " ${STANDALONE_TESTS[@]} " =~ " ${file} " ]]; then 123 | continue 124 | fi 125 | EXCLUSION_LIST_FILES+=("$file") 126 | done < <(find "$dir" -mindepth 1 -type f -name '*Test.php' -print0) 127 | done 128 | 129 | ## run over EXCLUSION_LIST_FILES and call add_dir_to_line for each file 130 | MAX_DIRS_PER_LINE=10 131 | dir_count=MAX_DIRS_PER_LINE-1 132 | add_dir_to_line "" 133 | for file in "${EXCLUSION_LIST_FILES[@]}"; do 134 | add_dir_to_line "$file" 135 | done 136 | 137 | ## run over STANDALONE_TESTS and call add_dir_to_line for each file 138 | MAX_DIRS_PER_LINE=1 139 | dir_count=MAX_DIRS_PER_LINE-1 140 | add_dir_to_line "" 141 | for file in "${STANDALONE_TESTS[@]}"; do 142 | add_dir_to_line "$file" 143 | done 144 | 145 | # Handle the last line if it's not empty 146 | if [ -n "$current_line" ]; then 147 | json_content="$json_content$current_line" 148 | fi 149 | 150 | # Close the JSON string 151 | json_content="$json_content\"\n\t]\n}\n" 152 | 153 | # Write to the output file 154 | echo -e "$json_content" > "$OUTPUT_FILE" 155 | 156 | ####### 157 | echo "testsuite_dirs=$(jq -c .testsuites integration-testsuites.json)" >> "$GITHUB_OUTPUT" 158 | 159 | - name: Debug output 160 | run: | 161 | echo "PHP Versions: ${{ steps.set-matrix.outputs.php_versions }}" 162 | echo "database Versions: ${{ steps.set-matrix.outputs.database_versions }}" 163 | echo "search Versions: ${{ steps.set-matrix.outputs.search_versions }}" 164 | echo "message_queue Versions: ${{ steps.set-matrix.outputs.message_queue_versions }}" 165 | echo "cache Versions: ${{ steps.set-matrix.outputs.cache_versions }}" 166 | echo "http_cache Versions: ${{ steps.set-matrix.outputs.http_cache_versions }}" 167 | echo "testsuite_dirs: ${{ steps.set-matrix-testsuite.outputs.testsuite_dirs }}" 168 | 169 | run-integration-tests: 170 | needs: [matrix-calculator] 171 | strategy: 172 | fail-fast: false 173 | matrix: 174 | php_version: ${{ fromJSON(needs.matrix-calculator.outputs.php_versions) }} 175 | database_version: ${{ fromJSON(needs.matrix-calculator.outputs.database_versions) }} 176 | search_version: ${{ fromJSON(needs.matrix-calculator.outputs.search_versions) }} 177 | message_queue_version: ${{ fromJSON(needs.matrix-calculator.outputs.message_queue_versions) }} 178 | cache_version: ${{ fromJSON(needs.matrix-calculator.outputs.cache_versions) }} 179 | http_cache_version: ${{ fromJSON(needs.matrix-calculator.outputs.http_cache_versions) }} 180 | testsuite_dirs: ${{ fromJSON(needs.matrix-calculator.outputs.testsuite_dirs) }} 181 | runs-on: ubuntu-latest 182 | steps: 183 | - name: Checkout commit 184 | uses: actions/checkout@v4 185 | with: 186 | repository: ${{ github.event.inputs.repository }} 187 | ref: ${{ github.event.inputs.head }} 188 | path: main 189 | fetch-depth: 0 190 | 191 | - name: Setup Warden Environment 192 | uses: mage-os/github-actions/warden/setup-environment@main 193 | with: 194 | run_composer_install: 1 195 | php_version: ${{ matrix.php_version }} 196 | database: ${{ matrix.database_version }} 197 | search: ${{ matrix.search_version }} 198 | rabbitmq: ${{ matrix.message_queue_version }} 199 | redis: ${{ matrix.cache_version }} 200 | varnish: ${{ matrix.http_cache_version }} 201 | base_directory: "./main" 202 | 203 | - name: Setup configs for Integration Tests 204 | uses: mage-os/github-actions/warden/integration-tests@main 205 | with: 206 | search: ${{ matrix.search_version }} 207 | rabbitmq: ${{ matrix.message_queue_version }} 208 | redis: ${{ matrix.cache_version }} 209 | run_memory_test: 0 210 | run_magento_integration_tests: 0 211 | run_magento_integration_tests_real_suite: 0 212 | base_directory: "./main" 213 | 214 | - name: Create Mage-OS testsuite 215 | working-directory: ./main/dev/tests/integration 216 | run: | 217 | FILE="phpunit.xml.dist" 218 | 219 | # Remove Memory Usage Tests and Magento Integration Tests Real Suite test suites 220 | sed -i '//,/<\/testsuite>/d' "$FILE" 221 | sed -i '//,/<\/testsuite>/d' "$FILE" 222 | 223 | DIRS="${{ matrix.testsuite_dirs }}" 224 | echo "Debug: $DIRS" 225 | NEW_TESTSUITE_ENTRY=$( 226 | echo "" 227 | IFS=','; for dir in $DIRS; do echo " $dir"; done 228 | echo " testsuite/Magento/IntegrationTest.php" 229 | echo "" 230 | ) 231 | echo "Debug: $NEW_TESTSUITE_ENTRY" 232 | awk -v new_testsuite="$NEW_TESTSUITE_ENTRY" '/<\/testsuites>/ { print new_testsuite; found=1 } {print} END { if (!found) print new_testsuite }' "$FILE" > tmpfile && mv tmpfile "$FILE" 233 | echo "\nMage-OS suite has been added to $FILE \n" 234 | 235 | ## TODO: I want to have a possibility to NOT ignore those test if I wish to - by adding additional input to github actions, for example 236 | sed -i '//i\\\integrationIgnore<\/group><\/exclude><\/groups>' "$FILE" 237 | echo "\nIgnore group `integrationIgnore` has been added to $FILE \n" 238 | 239 | cat $FILE; 240 | 241 | - name: Run Integration Tests for Modules 242 | working-directory: ./main 243 | run: | 244 | export WARDEN="$(dirname $(pwd))/warden/bin/warden" 245 | # Important: Run the custom "Magento Integration Tests" test suite, which runs all other test suites 246 | ${WARDEN} env exec -T --workdir /var/www/html/dev/tests/integration php-fpm ../../../vendor/bin/phpunit --configuration phpunit.xml.dist --testsuite 'Magento Integration Tests' --log-junit=../../../phpunit-output/junit/res-log.xml 247 | 248 | rum-memory-integration-tests: 249 | needs: [ matrix-calculator ] 250 | strategy: 251 | fail-fast: false 252 | matrix: 253 | php_version: ${{ fromJSON(needs.matrix-calculator.outputs.php_versions) }} 254 | database_version: ${{ fromJSON(needs.matrix-calculator.outputs.database_versions) }} 255 | search_version: ${{ fromJSON(needs.matrix-calculator.outputs.search_versions) }} 256 | message_queue_version: ${{ fromJSON(needs.matrix-calculator.outputs.message_queue_versions) }} 257 | cache_version: ${{ fromJSON(needs.matrix-calculator.outputs.cache_versions) }} 258 | http_cache_version: ${{ fromJSON(needs.matrix-calculator.outputs.http_cache_versions) }} 259 | runs-on: ubuntu-latest 260 | steps: 261 | - name: Checkout commit 262 | uses: actions/checkout@v4 263 | with: 264 | repository: ${{ github.event.inputs.repository }} 265 | ref: ${{ github.event.inputs.head }} 266 | path: main 267 | fetch-depth: 0 268 | 269 | - name: Setup Warden Environment 270 | uses: mage-os/github-actions/warden/setup-environment@main 271 | with: 272 | run_composer_install: 1 273 | php_version: ${{ matrix.php_version }} 274 | database: ${{ matrix.database_version }} 275 | search: ${{ matrix.search_version }} 276 | rabbitmq: ${{ matrix.message_queue_version }} 277 | redis: ${{ matrix.cache_version }} 278 | varnish: ${{ matrix.http_cache_version }} 279 | base_directory: "./main" 280 | 281 | - name: Run Integration tests 282 | uses: mage-os/github-actions/warden/integration-tests@main 283 | with: 284 | search: ${{ matrix.search_version }} 285 | rabbitmq: ${{ matrix.message_queue_version }} 286 | redis: ${{ matrix.cache_version }} 287 | run_memory_test: "true" 288 | base_directory: "./main" 289 | -------------------------------------------------------------------------------- /.github/workflows/integration-README.md: -------------------------------------------------------------------------------- 1 | # Integration Tests for a Magento Package 2 | 3 | A Github Workflow that runs the Integration Tests of a Magento Package 4 | 5 | ## Inputs 6 | 7 | See the [integration.yaml](./integration.yaml) 8 | 9 | | Input | Description | Required | Default | 10 | | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ----------------------------- | 11 | | matrix | JSON string of [version matrix for Magento](./#matrix-format) | true | NULL | 12 | | 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 | 13 | | package_name | The name of the package | true | NULL | 14 | | source_folder | The source folder of the package | false | $GITHUB_WORKSPACE | 15 | | magento_directory | The folder where Magento will be installed | false | ../magento2 | 16 | | magento_repository | Where to install Magento from | false | https://mirror.mage-os.org/ | 17 | | test_command | The integration test command to run | false | "../../../vendor/bin/phpunit" | 18 | | composer_cache_key | A key to version the composer cache. Can be incremented if you need to bust the cache. | false | "" | 19 | 20 | ## Secrets 21 | | Input | Description | Required | Default | 22 | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------- | 23 | | composer_auth | JSON string of [composer credentials](https://devdocs.magento.com/guides/v2.4/install-gde/prereq/connect-auth.html) | false | NULL | 24 | 25 | ### Matrix Format 26 | 27 | The Magento matrix format outlined by the [supported versions action.](https://github.com/mage-os/github-actions/tree/main/supported-version/supported.json) 28 | 29 | 30 | ## Usage 31 | 32 | ```yml 33 | name: Integration Test 34 | 35 | on: 36 | push: 37 | branches: 38 | - main 39 | pull_request: 40 | branches: 41 | - main 42 | 43 | jobs: 44 | compute_matrix: 45 | runs-on: ubuntu-latest 46 | outputs: 47 | matrix: ${{ steps.supported-version.outputs.matrix }} 48 | steps: 49 | - uses: actions/checkout@v2 50 | - uses: mage-os/github-actions/supported-version@main 51 | id: supported-version 52 | - run: echo ${{ steps.supported-version.outputs.matrix }} 53 | integration-workflow: 54 | needs: compute_matrix 55 | uses: mage-os/github-actions/.github/workflows/integration.yaml@main 56 | with: 57 | package_name: my-vendor/package 58 | matrix: ${{ needs.compute_matrix.outputs.matrix }} 59 | test_command: ../../../vendor/bin/phpunit ../../../vendor/my-vendor/package/Test/Integration 60 | secrets: 61 | composer_auth: ${{ secrets.COMPOSER_AUTH }} 62 | ``` 63 | -------------------------------------------------------------------------------- /.github/workflows/integration.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_call: 3 | inputs: 4 | use_local_source: 5 | type: boolean 6 | required: false 7 | default: true 8 | description: "Whether or not you want to test your local package or not." 9 | 10 | source_folder: 11 | type: string 12 | required: false 13 | default: $GITHUB_WORKSPACE 14 | description: "The source folder of the package" 15 | 16 | package_name: 17 | type: string 18 | required: true 19 | description: "The name of the package" 20 | 21 | magento_directory: 22 | type: string 23 | required: false 24 | default: "../magento2" 25 | description: "The folder where Magento will be installed" 26 | 27 | magento_repository: 28 | type: string 29 | required: false 30 | default: "https://mirror.mage-os.org/" 31 | description: "Where to install Magento from" 32 | 33 | matrix: 34 | type: string 35 | required: true 36 | description: "The matrix of Magento versions to test against" 37 | 38 | fail-fast: 39 | type: boolean 40 | required: false 41 | default: true 42 | 43 | test_command: 44 | type: string 45 | required: false 46 | default: ../../../vendor/bin/phpunit 47 | description: "The integration test command to run" 48 | 49 | composer_cache_key: 50 | type: string 51 | required: false 52 | default: '' 53 | description: A key to version the composer cache. Can be incremented if you need to bust the cache. 54 | 55 | secrets: 56 | composer_auth: 57 | required: false 58 | 59 | jobs: 60 | integration_test: 61 | runs-on: ${{ matrix.os }} 62 | strategy: 63 | fail-fast: ${{ inputs.fail-fast }} 64 | matrix: ${{ fromJSON(inputs.matrix) }} 65 | services: 66 | elasticsearch: 67 | image: ${{ matrix.elasticsearch || '' }} 68 | env: 69 | # By default, ElasticSearch refuses to spawn in single node configuration, as it expects redundancy. 70 | # This is a dev environment, so redundancy is just wasteful. 71 | discovery.type: single-node 72 | # Disable HTTPS and password authentication 73 | # this is a local dev environment, so the added CA chain complexity is an extreme overkill 74 | xpack.security.enabled: false 75 | xpack.security.http.ssl.enabled: false 76 | xpack.security.transport.ssl.enabled: false 77 | 78 | options: >- 79 | --health-cmd "curl http://localhost:9200/_cluster/health" 80 | --health-interval 10s 81 | --health-timeout 5s 82 | --health-retries 10 83 | ports: 84 | - 9200:9200 85 | 86 | opensearch: 87 | image: ${{ matrix.opensearch || '' }} 88 | env: 89 | # By default, ElasticSearch refuses to spawn in single node configuration, as it expects redundancy. 90 | # This is a dev environment, so redundancy is just wasteful. 91 | discovery.type: single-node 92 | # Disable HTTPS and password authentication 93 | DISABLE_INSTALL_DEMO_CONFIG: true 94 | DISABLE_SECURITY_PLUGIN: true 95 | 96 | options: >- 97 | --health-cmd "curl http://localhost:9200/_cluster/health" 98 | --health-interval 10s 99 | --health-timeout 5s 100 | --health-retries 10 101 | ports: 102 | - 9200:9200 103 | 104 | mysql: 105 | image: ${{ matrix.mysql }} 106 | env: 107 | MYSQL_DATABASE: magento_integration_tests 108 | MYSQL_USER: user 109 | MYSQL_PASSWORD: password 110 | MYSQL_ROOT_PASSWORD: rootpassword 111 | ports: 112 | - 3306:3306 113 | options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 114 | 115 | rabbitmq: 116 | image: ${{ matrix.rabbitmq }} 117 | env: 118 | RABBITMQ_DEFAULT_USER: guest 119 | RABBITMQ_DEFAULT_PASS: guest 120 | ports: 121 | - 5672:5672 122 | steps: 123 | - uses: actions/checkout@v4 124 | - name: Set PHP Version 125 | uses: shivammathur/setup-php@v2 126 | with: 127 | php-version: ${{ matrix.php }} 128 | tools: composer:v${{ matrix.composer }} 129 | coverage: none 130 | 131 | - name: Allow SQL triggers 132 | run: | 133 | mysql --host 127.0.0.1 --port ${{ job.services.mysql.ports['3306'] }} -u root -prootpassword -e "set global log_bin_trust_function_creators=1;" 134 | 135 | - run: composer create-project --repository-url="${{ inputs.magento_repository }}" "${{ matrix.magento }}" ${{ inputs.magento_directory }} --no-install 136 | shell: bash 137 | env: 138 | COMPOSER_AUTH: ${{ secrets.composer_auth }} 139 | name: Create Magento ${{ matrix.magento }} Project 140 | 141 | - uses: mage-os/github-actions/get-magento-version@main 142 | id: magento-version 143 | with: 144 | working-directory: ${{ inputs.magento_directory }} 145 | 146 | - name: Get Composer Cache Directory 147 | shell: bash 148 | working-directory: ${{ inputs.magento_directory }} 149 | id: composer-cache 150 | run: | 151 | echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT 152 | 153 | 154 | - name: "Cache Composer Packages" 155 | uses: actions/cache@v4 156 | with: 157 | key: "composer | v5 | ${{ inputs.composer_cache_key }} | ${{ hashFiles('composer.lock') }} | ${{ matrix.os }} | ${{ matrix.composer }} | ${{ matrix.php }} | ${{ matrix.magento }}" 158 | path: ${{ steps.composer-cache.outputs.dir }} 159 | 160 | - run: composer config repositories.local path ${{ inputs.source_folder }} 161 | name: Add Github Repo for Testing 162 | working-directory: ${{ inputs.magento_directory }} 163 | shell: bash 164 | if: ${{ inputs.use_local_source == true }} 165 | 166 | - run: composer require monolog/monolog:"<2.7.0" --no-update 167 | name: Fixup Monolog (https://github.com/magento/magento2/pull/35596) 168 | working-directory: ${{ inputs.magento_directory }} 169 | if: | 170 | steps.magento-version.outputs.version == '"2.4.4"' 171 | 172 | - run: composer require "dotmailer/dotmailer-magento2-extension-package:4.6.0-p2 as 4.6.0" --no-update 173 | name: Fixup Dotmailer (https://devdocs.magento.com/guides/v2.4/release-notes/release-notes-2-4-0-commerce.html#dotdigital-1) 174 | working-directory: ${{ inputs.magento_directory }} 175 | if: | 176 | steps.magento-version.outputs.version == '"2.4.0"' 177 | 178 | - run: | 179 | composer config --no-interaction allow-plugins.dealerdirect/phpcodesniffer-composer-installer true 180 | composer config --no-interaction allow-plugins.laminas/laminas-dependency-plugin true 181 | composer config --no-interaction allow-plugins.magento/* true 182 | name: Fixup Composer Plugins 183 | working-directory: ${{ inputs.magento_directory }} 184 | if: ${{ !startsWith(matrix.composer, '1') }} 185 | 186 | - run: | 187 | composer global require hirak/prestissimo 188 | name: Install composer plugin for parallel downloads 189 | working-directory: ${{ inputs.magento_directory }} 190 | if: ${{ startsWith(matrix.composer, '1') }} 191 | 192 | - run: composer require ${{ inputs.package_name }} "@dev" --no-update && composer install 193 | name: Require and attempt install 194 | working-directory: ${{ inputs.magento_directory }} 195 | shell: bash 196 | env: 197 | COMPOSER_CACHE_DIR: ${{ steps.composer-cache.outputs.dir }} 198 | COMPOSER_AUTH: ${{ secrets.composer_auth }} 199 | 200 | - name: Replace Configuration Settings for env 201 | working-directory: ${{ inputs.magento_directory }}/dev/tests/integration 202 | run: | 203 | sed -i "s/'db-host' => 'localhost'/'db-host' => '127.0.0.1'/" etc/install-config-mysql.php.dist 204 | sed -i "s/'db-user' => 'root'/'db-user' => 'user'/" etc/install-config-mysql.php.dist 205 | sed -i "s/'db-password' => '123123q'/'db-password' => 'password'/" etc/install-config-mysql.php.dist 206 | sed -i "s/'elasticsearch-host' => 'localhost'/'elasticsearch-host' => '127.0.0.1'/" etc/install-config-mysql.php.dist 207 | sed -i "s/'amqp-host' => 'localhost'/'amqp-host' => '127.0.0.1'/" etc/install-config-mysql.php.dist 208 | 209 | # mysql server 5.7 doesn't have the column-statistics expected by mysql client 8 (failing 2.3.7-p* builds) 210 | # ref: https://gist.github.com/tobias-khs/8dcf82f719a2b3a7c3b9604b4df53bbf 211 | - name: Switch from mysql-client 8 to mysql-client 5.7 212 | if: | 213 | steps.magento-version.outputs.version == '"2.3.7-p3"' || steps.magento-version.outputs.version == '"2.3.7-p4"' 214 | run: | 215 | mkdir -p /tmp/mysql-5.7 216 | cd /tmp/mysql-5.7 217 | sudo apt-get purge mysql-server mysql-client mysql-common mysql-server-core-* mysql-client-core-* 218 | sudo rm -rf /etc/mysql /var/lib/mysql 219 | sudo apt-get autoremove 220 | sudo apt-get autoclean 221 | wget --quiet https://downloads.mysql.com/archives/get/p/23/file/mysql-server_5.7.30-1ubuntu18.04_amd64.deb-bundle.tar 222 | tar -xf mysql-server_5.7.30-1ubuntu18.04_amd64.deb-bundle.tar 223 | sudo dpkg -i mysql-common_5.7.30-1ubuntu18.04_amd64.deb 224 | sudo dpkg -i libmysqlclient20_5.7.30-1ubuntu18.04_amd64.deb 225 | sudo dpkg -i mysql-community-client_5.7.30-1ubuntu18.04_amd64.deb 226 | sudo dpkg -i mysql-client_5.7.30-1ubuntu18.04_amd64.deb 227 | sudo dpkg -i libmysqlclient20_5.7.30-1ubuntu18.04_amd64.deb 228 | mysqldump --version 229 | 230 | - run: ${{ inputs.test_command }} 231 | working-directory: ${{ inputs.magento_directory }}/dev/tests/integration 232 | name: Run Integration Tests 233 | 234 | - name: Upload test sandbox dir 235 | uses: actions/upload-artifact@v4 236 | if: failure() 237 | with: 238 | name: sandbox-data-${{ steps.magento-version.outputs.version }} 239 | path: /home/runner/work/infrastructure/magento2/dev/tests/integration/tmp/sandbox-* 240 | retention-days: 3 241 | 242 | -------------------------------------------------------------------------------- /.github/workflows/nx-integration-tests.yml: -------------------------------------------------------------------------------- 1 | name: NX Integration Test 2 | #description: Workflow to run NX assisted integration tests for Mage-OS projects. 3 | on: 4 | workflow_call: 5 | inputs: 6 | repository: 7 | type: string 8 | description: "Repository" 9 | required: true 10 | pr_head: 11 | type: string 12 | description: "head SHA" 13 | required: true 14 | pr_base: 15 | type: string 16 | description: "pr base SHA" 17 | required: true 18 | workflow_dispatch: 19 | inputs: 20 | repository: 21 | type: string 22 | description: "Repository" 23 | required: true 24 | pr_head: 25 | type: string 26 | description: "head SHA" 27 | required: true 28 | pr_base: 29 | type: string 30 | description: "pr base SHA" 31 | required: true 32 | 33 | jobs: 34 | debug: 35 | name: Debug 36 | runs-on: ubuntu-latest 37 | steps: 38 | - name: debug 39 | shell: bash 40 | env: 41 | repository: ${{ inputs.repository }} 42 | pr_head: ${{ inputs.pr_head }} 43 | pr_base: ${{ inputs.pr_base }} 44 | run: | 45 | echo "input was" 46 | echo "repository: ${repository}" 47 | echo "pr_head: ${pr_head}" 48 | echo "pr_base: ${pr_base}" 49 | 50 | matrix-calculator: 51 | outputs: 52 | php_versions: ${{ steps.calculate-matrix.outputs.php_versions }} 53 | database_versions: ${{ steps.calculate-matrix.outputs.database_versions }} 54 | search_versions: ${{ steps.calculate-matrix.outputs.search_versions }} 55 | message_queue_versions: ${{ steps.calculate-matrix.outputs.message_queue_versions }} 56 | cache_versions: ${{ steps.calculate-matrix.outputs.cache_versions }} 57 | http_cache_versions: ${{ steps.calculate-matrix.outputs.http_cache_versions }} 58 | 59 | runs-on: ubuntu-latest 60 | steps: 61 | - name: Run Matrix Calulator 62 | id: calculate-matrix 63 | uses: mage-os/github-actions/supported-services-matrix-calculator@main 64 | with: 65 | repository: ${{ inputs.repository }} 66 | ref: ${{ inputs.pr_head }} 67 | 68 | - name: Calculated Result 69 | shell: bash 70 | env: 71 | php_versions: ${{ steps.calculate-matrix.outputs.php_versions }} 72 | database_versions: ${{ steps.calculate-matrix.outputs.database_versions }} 73 | search_versions: ${{ steps.calculate-matrix.outputs.search_versions }} 74 | message_queue_versions: ${{ steps.calculate-matrix.outputs.message_queue_versions }} 75 | cache_versions: ${{ steps.calculate-matrix.outputs.cache_versions }} 76 | http_cache_versions: ${{ steps.calculate-matrix.outputs.http_cache_versions }} 77 | run: | 78 | echo "PHP Versions: $php_versions" 79 | echo "database_versions: $database_versions" 80 | echo "search_versions: $search_versions" 81 | echo "message_queue_versions: $message_queue_versions" 82 | echo "cache_versions: $cache_versions" 83 | echo "http_cache_versions: $http_cache_versions" 84 | 85 | nx-project-setup: 86 | runs-on: ubuntu-latest 87 | steps: 88 | - name: Run Nx Project Setup 89 | uses: mage-os/github-actions/nx-integration-tests-setup@main 90 | with: 91 | repository: ${{ inputs.repository }} 92 | ref: ${{ inputs.pr_head }} 93 | pr_base: ${{ inputs.pr_base }} 94 | 95 | integration-tests: 96 | needs: 97 | - matrix-calculator 98 | - nx-project-setup 99 | strategy: 100 | fail-fast: false 101 | matrix: 102 | php_version: ${{ fromJSON(needs.matrix-calculator.outputs.php_versions) }} 103 | database_version: ${{ fromJSON(needs.matrix-calculator.outputs.database_versions) }} 104 | search_version: ${{ fromJSON(needs.matrix-calculator.outputs.search_versions) }} 105 | message_queue_version: ${{ fromJSON(needs.matrix-calculator.outputs.message_queue_versions) }} 106 | cache_version: ${{ fromJSON(needs.matrix-calculator.outputs.cache_versions) }} 107 | http_cache_version: ${{ fromJSON(needs.matrix-calculator.outputs.http_cache_versions) }} 108 | runs-on: ubuntu-latest 109 | steps: 110 | - name: Project Cache 111 | uses: actions/cache/restore@v4 112 | with: 113 | path: main 114 | key: ${{ runner.os }}-project-${{ inputs.ref }} 115 | 116 | # could probably swap this to a docker container in future 117 | - name: Install NX 118 | working-directory: ./main 119 | run: | 120 | npm install -g nx@^15.4 121 | 122 | - name: Print Affected 123 | working-directory: ./main 124 | run: | 125 | AFFECTED_OUTPUT=/tmp/affect.json 126 | nx print-affected --head=HEAD --base=remotes/origin/${{ inputs.pr_base }} > ${AFFECTED_OUTPUT} 127 | cat ${AFFECTED_OUTPUT} 128 | echo "Affected Projects: $(jq .projects ${AFFECTED_OUTPUT})" 129 | 130 | - name: Setup Warden Environment 131 | uses: mage-os/github-actions/warden/setup-environment@main 132 | with: 133 | php_version: ${{ matrix.php_version }} 134 | database: ${{ matrix.database_version }} 135 | search: ${{ matrix.search_version }} 136 | rabbitmq: ${{ matrix.message_queue_version }} 137 | redis: ${{ matrix.cache_version }} 138 | varnish: ${{ matrix.http_cache_version }} 139 | base_directory: "./main" 140 | 141 | - name: Setup config for Integration tests 142 | uses: mage-os/github-actions/warden/integration-tests@main 143 | with: 144 | search: ${{ matrix.search_version }} 145 | rabbitmq: ${{ matrix.message_queue_version }} 146 | redis: ${{ matrix.cache_version }} 147 | run_memory_test: 0 148 | run_magento_integration_tests: 0 149 | run_magento_integration_tests_real_suite: 0 150 | base_directory: "./main" 151 | 152 | - name: Run Integration Tests (Real) 153 | working-directory: ./main 154 | run: | 155 | export WARDEN="$(dirname $(pwd))/warden/bin/warden" 156 | nx affected --target=test:integration --head=HEAD --base=remotes/origin/${{ inputs.pr_base }} 157 | -------------------------------------------------------------------------------- /.github/workflows/release-please.yml: -------------------------------------------------------------------------------- 1 | name: Create Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | release-please: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: google-github-actions/release-please-action@v4 13 | with: 14 | token: ${{ secrets.MAGE_OS_CI_TOKEN }} 15 | command: manifest 16 | default-branch: main 17 | -------------------------------------------------------------------------------- /.github/workflows/sansec-ecomscan.yml: -------------------------------------------------------------------------------- 1 | name: Sansec eComscan Security Scan 2 | 3 | on: 4 | push: 5 | pull_request_target: 6 | workflow_dispatch: 7 | 8 | jobs: 9 | run-ecomscan: 10 | # Skip if it's a push event on a PR (it can't access secrets) 11 | if: github.event.pull_request == null || github.event_name != 'push' 12 | name: Run Sansec eComscan 13 | runs-on: ubuntu-latest 14 | permissions: 15 | contents: read 16 | pull-requests: read 17 | 18 | steps: 19 | - name: Checkout repository 20 | uses: actions/checkout@v4 21 | with: 22 | ref: ${{ github.event.pull_request.head.sha }} 23 | persist-credentials: false 24 | 25 | - name: Download eComscan 26 | run: wget https://ecomscan.com/downloads/linux-amd64/ecomscan 27 | 28 | - name: Fix permissions 29 | run: chmod +x ecomscan 30 | 31 | - name: Run eComscan 32 | env: 33 | ECOMSCAN_KEY: ${{ secrets.SANSEC_LICENSE_KEY }} 34 | run: | 35 | output=$(./ecomscan --no-auto-update --skip-database --deep --format=csv .) 36 | if [ -n "$output" ]; then 37 | echo "Security issues found:" 38 | echo "$output" 39 | exit 1 40 | fi 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.18.0 -------------------------------------------------------------------------------- /.release-please-manifest.json: -------------------------------------------------------------------------------- 1 | {".":"1.7.0"} 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint" 4 | ] 5 | } -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @Mage-OS/infrastructure -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment 10 | include: 11 | 12 | * Using welcoming and inclusive language 13 | * Being respectful of differing viewpoints and experiences 14 | * Gracefully accepting constructive criticism 15 | * Focusing on what is best for the community 16 | * Showing empathy towards other community members 17 | 18 | Examples of unacceptable behavior by participants include: 19 | 20 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 21 | * Trolling, insulting/derogatory comments, and personal or political attacks 22 | * Public or private harassment 23 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 24 | * Other conduct which could reasonably be considered inappropriate in a professional setting 25 | 26 | ## Our Responsibilities 27 | 28 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 29 | 30 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 31 | 32 | ## Scope 33 | 34 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 35 | 36 | ## Enforcement 37 | 38 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project lead at [board@mage-os.org](mailto:board@mage-os.org). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 39 | 40 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 41 | 42 | ## Attribution 43 | 44 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 45 | 46 | [homepage]: https://www.contributor-covenant.org 47 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Github Actions for Magento 2 2 | 3 | We would love for you to contribute to "Github Actions for Magento 2" and help make it even better than it is 4 | today! As a contributor, here are the guidelines we would like you to follow: 5 | 6 | - [Code of Conduct](#coc) 7 | - [Question or Problem?](#question) 8 | - [Issues and Bugs](#issue) 9 | - [Feature Requests](#feature) 10 | - [Submission Guidelines](#submit) 11 | - [Coding Rules](#rules) 12 | - [Commit Message Guidelines](#commit) 13 | 14 | ## Code of Conduct 15 | Help us keep "Github Actions for Magento 2" open and inclusive. Please read and follow our [Code of Conduct][coc]. 16 | 17 | ## Got a Question or Problem? 18 | 19 | Do not open issues for general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [Discussions](https://github.com/mage-os/github-actions/discussions). 20 | 21 | To save your and our time, we will systematically close all issues that are requests for general support and redirect people to [Discussions](https://github.com/mage-os/github-actions/discussions). 22 | 23 | ## Found a Bug? 24 | If you find a bug in the source code, you can help us by 25 | [submitting an issue](#submit-issue) to our [GitHub Repository][github]. Even better, you can 26 | [submit a Pull Request](#submit-pr) with a fix. 27 | 28 | ## Missing a Feature? 29 | You can *request* a new feature by [submitting an issue](#submit-issue) to our GitHub 30 | Repository. If you would like to *implement* a new feature, please submit an issue with 31 | a proposal for your work first, to be sure that we can use it. 32 | Please consider what kind of change it is: 33 | 34 | * For a **Major Feature**, first open an issue and outline your proposal so that it can be 35 | discussed. This will also allow us to better coordinate our efforts, prevent duplication of work, 36 | and help you to craft the change so that it is successfully accepted into the project. 37 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr). 38 | 39 | ## Submission Guidelines 40 | 41 | ### Submitting an Issue 42 | 43 | Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available. 44 | 45 | We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we will systematically ask you to provide a minimal reproduction scenario using https://github.com/. Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like: 46 | 47 | - version of "Github Actions for Magento 2" used 48 | - 3rd-party libraries and their versions 49 | - and most importantly - a use-case that fails 50 | 51 | A minimal reproduce scenario using https://github.com/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem. 52 | 53 | We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal reproduction. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it. 54 | 55 | Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced. 56 | 57 | You can file new issues by filling out our [new issue form](https://github.com/mage-os/github-actions/issues/new/choose). 58 | 59 | 60 | ### Submitting a Pull Request (PR) 61 | Before you submit your Pull Request (PR) consider the following guidelines: 62 | 63 | 1. Search [GitHub](https://github.com/mage-os/github-actions/pulls) for an open or closed PR 64 | that relates to your submission. You don't want to duplicate effort. 65 | 1. Fork the [mage-os/github-actions](https://github.com/mage-os/github-actions) repo. 66 | 1. Make your changes in a new git branch: 67 | 68 | ```shell 69 | git checkout -b my-fix-branch master 70 | ``` 71 | 72 | 1. Create your patch, **including appropriate test cases**. 73 | 1. Follow our [Coding Rules](#rules). 74 | 1. Run the full test suite, as described in the [developer documentation][dev-doc], 75 | and ensure that all tests pass. 76 | 1. Commit your changes using a descriptive commit message that follows our 77 | [commit message conventions](#commit). Adherence to these conventions 78 | is necessary because release notes are automatically generated from these messages. 79 | 80 | ```shell 81 | git commit -a 82 | ``` 83 | Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files. 84 | 85 | 1. Push your branch to GitHub: 86 | 87 | ```shell 88 | git push origin my-fix-branch 89 | ``` 90 | 91 | 1. In GitHub, send a pull request to `github-actions-magento2:main`. 92 | * If we suggest changes then: 93 | * Make the required updates. 94 | * Re-run the "Github Actions for Magento 2" test suites to ensure tests are still passing. 95 | * Rebase your branch and force push to your GitHub repository (this will update your Pull Request): 96 | 97 | ```shell 98 | git rebase main -i 99 | git push -f 100 | ``` 101 | * Note: don't squash your branch until after the reviewers comment "lgtm", so they don't need to re-review your entire branch every commit. 102 | 103 | That's it! Thank you for your contribution! 104 | 105 | #### After your pull request is merged 106 | 107 | After your pull request is merged, you can safely delete your branch and pull the changes 108 | from the main (upstream) repository: 109 | 110 | * Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows: 111 | 112 | ```shell 113 | git push origin --delete my-fix-branch 114 | ``` 115 | 116 | * Check out the main branch: 117 | 118 | ```shell 119 | git checkout main -f 120 | ``` 121 | 122 | * Delete the local branch: 123 | 124 | ```shell 125 | git branch -D my-fix-branch 126 | ``` 127 | 128 | * Update your main with the latest upstream version: 129 | 130 | ```shell 131 | git pull --ff upstream main 132 | ``` 133 | 134 | ## Coding Rules 135 | To ensure consistency throughout the source code, keep these rules in mind as you are working: 136 | 137 | * All features or bug fixes **must be tested** by one or more specs (unit-tests). 138 | * All public API methods **must be documented**. (Details TBC). 139 | 140 | ## Commit Message Guidelines 141 | 142 | We have very precise rules over how our git commit messages can be formatted. This leads to **more 143 | readable messages** that are easy to follow when looking through the **project history**. 144 | 145 | ### Commit Message Format 146 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special 147 | format that includes a **type**, a **scope** and a **subject**: 148 | 149 | ``` 150 | (): 151 | 152 | 153 | 154 |