diff --git a/.github/scripts/.gitignore b/.github/scripts/.gitignore new file mode 100644 index 0000000000..f06235c460 --- /dev/null +++ b/.github/scripts/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist diff --git a/.github/scripts/find-artifact.ts b/.github/scripts/find-artifact.ts new file mode 100644 index 0000000000..3f3524c9cc --- /dev/null +++ b/.github/scripts/find-artifact.ts @@ -0,0 +1,63 @@ +import * as core from "@actions/core"; +import * as github from "@actions/github"; + +interface Inputs { + github: ReturnType; + context: typeof github.context; + core: typeof core; +} + +module.exports = async ({github, context, core}: Inputs) => { + const commitSha = process.env.BASE_SHA; + const artifactName = process.env.ARTIFACT_NAME; + const workflowName = process.env.WORKFLOW_NAME; + + // Get all workflow runs for this commit + const runs = await github.rest.actions.listWorkflowRunsForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + per_page: 20, + event: "push", + head_sha: commitSha + }); + + if (runs.data.workflow_runs.length === 0) { + core.setFailed(`No workflow runs found for commit ${commitSha}`); + return; + } + + const workflowRuns = runs.data.workflow_runs; + if (workflowRuns.length === 0) { + core.setFailed(`No workflow runs found for commit ${commitSha}`); + return; + } + + let found = false; + for (const run of workflowRuns) { + if (run.status !== "completed" || run.conclusion !== "success") { + continue; + } + + if (run.name !== workflowName) { + continue; + } + + const artifactsResp = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.id, + }); + + const artifact = artifactsResp.data.artifacts.find(a => a.name === artifactName); + if (artifact) { + core.setOutput("artifact_id", artifact.id.toString()); + core.setOutput("run_id", run.id.toString()); + found = true; + break; + } + } + + if (!found) { + core.setFailed(`No artifact named '${artifactName}' found for commit ${commitSha}`); + } +} diff --git a/.github/scripts/listPrefix.php b/.github/scripts/listPrefix.php new file mode 100644 index 0000000000..d7f902e855 --- /dev/null +++ b/.github/scripts/listPrefix.php @@ -0,0 +1,32 @@ +setFlags(RecursiveDirectoryIterator::SKIP_DOTS); +$files = new RecursiveIteratorIterator($iterator); + +$locations = []; +foreach ($files as $file) { + $path = $file->getPathname(); + if ($file->getExtension() !== 'php') { + continue; + } + $contents = file_get_contents($path); + $lines = explode("\n", $contents); + foreach ($lines as $i => $line) { + if (!str_contains($line, '_PHPStan_checksum')) { + continue; + } + + $trimmedPath = substr($path, strlen($dir) + 1); + if (str_starts_with($trimmedPath, 'vendor/composer/autoload_')) { + continue; + } + $locations[] = $trimmedPath . ':' . ($i + 1); + } +} +sort($locations); +echo implode("\n", $locations); +echo "\n"; diff --git a/.github/scripts/package-lock.json b/.github/scripts/package-lock.json new file mode 100644 index 0000000000..8f4f624afc --- /dev/null +++ b/.github/scripts/package-lock.json @@ -0,0 +1,323 @@ +{ + "name": "scripts", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "scripts", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@actions/core": "^1.11.1", + "@actions/github": "^6.0.1" + }, + "devDependencies": { + "@types/node": "^22.15.29", + "typescript": "^5.8.3" + } + }, + "node_modules/@actions/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz", + "integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==", + "license": "MIT", + "dependencies": { + "@actions/exec": "^1.1.1", + "@actions/http-client": "^2.0.1" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "@actions/io": "^1.0.1" + } + }, + "node_modules/@actions/github": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.1.tgz", + "integrity": "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==", + "license": "MIT", + "dependencies": { + "@actions/http-client": "^2.2.0", + "@octokit/core": "^5.0.1", + "@octokit/plugin-paginate-rest": "^9.2.2", + "@octokit/plugin-rest-endpoint-methods": "^10.4.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "undici": "^5.28.5" + } + }, + "node_modules/@actions/http-client": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", + "integrity": "sha512-mx8hyJi/hjFvbPokCg4uRd4ZX78t+YyRPtnKWwIl+RzNaVuFpQHfmlGVfsKEJN8LwTCvL+DfVgAM04XaHkm6bA==", + "license": "MIT", + "dependencies": { + "tunnel": "^0.0.6", + "undici": "^5.25.4" + } + }, + "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/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/@octokit/auth-token": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz", + "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==", + "license": "MIT", + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/core": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.1.tgz", + "integrity": "sha512-dKYCMuPO1bmrpuogcjQ8z7ICCH3FP6WmxpwC03yjzGfZhj9fTJg6+bS1+UAplekbN2C+M61UNllGOOoAfGCrdQ==", + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^4.0.0", + "@octokit/graphql": "^7.1.0", + "@octokit/request": "^8.4.1", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/endpoint": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz", + "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/graphql": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz", + "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==", + "license": "MIT", + "dependencies": { + "@octokit/request": "^8.4.1", + "@octokit/types": "^13.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "24.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", + "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz", + "integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz", + "integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^12.6.0" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@octokit/core": "5" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz", + "integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==", + "license": "MIT" + }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "12.6.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz", + "integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^20.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz", + "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==", + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^9.0.6", + "@octokit/request-error": "^5.1.1", + "@octokit/types": "^13.1.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/request-error": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz", + "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==", + "license": "MIT", + "dependencies": { + "@octokit/types": "^13.1.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@octokit/types": { + "version": "13.10.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz", + "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==", + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^24.2.0" + } + }, + "node_modules/@types/node": { + "version": "22.15.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.29.tgz", + "integrity": "sha512-LNdjOkUDlU1RZb8e1kOIUpN1qQUlzGkEtbVNo53vbrwDg5om6oduhm4SiUaPW5ASTXhAiP0jInWG8Qx9fVlOeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", + "license": "Apache-2.0" + }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", + "license": "ISC" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", + "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici": { + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "license": "MIT", + "dependencies": { + "@fastify/busboy": "^2.0.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/universal-user-agent": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz", + "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==", + "license": "ISC" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + } + } +} diff --git a/.github/scripts/package.json b/.github/scripts/package.json new file mode 100644 index 0000000000..e809b2ee73 --- /dev/null +++ b/.github/scripts/package.json @@ -0,0 +1,20 @@ +{ + "name": "scripts", + "version": "1.0.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "@actions/core": "^1.11.1", + "@actions/github": "^6.0.1" + }, + "devDependencies": { + "@types/node": "^22.15.29", + "typescript": "^5.8.3" + } +} diff --git a/.github/scripts/tsconfig.json b/.github/scripts/tsconfig.json new file mode 100644 index 0000000000..62ac6dae38 --- /dev/null +++ b/.github/scripts/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "target": "ES2020", + "module": "CommonJS", + "moduleResolution": "Node", + "esModuleInterop": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "outDir": "dist" + }, + "include": ["find-artifact.ts"] +} diff --git a/.github/workflows/checksum-phar.yml b/.github/workflows/checksum-phar.yml deleted file mode 100644 index 185fc779b4..0000000000 --- a/.github/workflows/checksum-phar.yml +++ /dev/null @@ -1,124 +0,0 @@ -# https://help.github.com/en/categories/automating-your-workflow-with-github-actions - -# This workflow checks that PHAR checksum changes only when it's supposed to -# It should stay the same when the PHAR contents do not change - -name: "Check PHAR checksum" - -on: - pull_request: - paths: - - 'compiler/**' - - '.github/workflows/checksum-phar.yml' - push: - branches: - - "2.1.x" - paths: - - 'compiler/**' - - '.github/workflows/checksum-phar.yml' - -concurrency: - group: checksum-phar-${{ github.head_ref || github.run_id }} # will be canceled on subsequent pushes in pull requests but not branches - cancel-in-progress: true - -jobs: - check-phar-checksum: - name: "Check PHAR checksum" - - runs-on: "ubuntu-latest" - timeout-minutes: 60 - - steps: - - name: "Checkout phpstan-dist" - uses: actions/checkout@v4 - with: - repository: phpstan/phpstan - path: phpstan-dist - ref: 2.1.x - - - name: "Get info" - id: info - working-directory: phpstan-dist - run: | - echo "checksum=$(head -n 1 .phar-checksum)" >> $GITHUB_OUTPUT - echo "commit=$(tail -n 1 .phar-checksum)" >> $GITHUB_OUTPUT - - - name: "Delete phpstan-dist" - run: "rm -r phpstan-dist" - - - name: "Checkout" - uses: actions/checkout@v4 - with: - ref: ${{ steps.info.outputs.commit }} - - - name: "Checkout latest PHAR compiler" - uses: actions/checkout@v4 - with: - path: phpstan-src - ref: ${{ github.sha }} - - - name: "Delete old compiler" - run: "rm -r compiler" - - - name: "Move new compiler" - run: "mv phpstan-src/compiler/ ." - - - name: "Delete phpstan-src" - run: "rm -r phpstan-src" - - - name: "Change and commit README.md" - run: | - echo Testing > README.md - git config --global user.name "phpstan-bot" - git config --global user.email "ondrej+phpstanbot@mirtes.cz" - git commit -a -m 'Changed README' - - - name: "Install PHP" - uses: "shivammathur/setup-php@v2" - with: - coverage: "none" - php-version: "8.1" - extensions: mbstring, intl - - - name: "Install dependencies" - run: "composer install --no-interaction --no-progress" - - - name: "Install compiler dependencies" - run: "composer install --no-interaction --no-progress --working-dir=compiler" - - # same steps as in phar.yml - - - name: "Prepare for PHAR compilation" - working-directory: "compiler" - run: "php bin/prepare" - - - name: "Set autoloader suffix" - run: "composer config autoloader-suffix PHPStanChecksum" - - - name: "Composer dump" - run: "composer install --no-interaction --no-progress" - env: - COMPOSER_ROOT_VERSION: "2.1.x-dev" - - - name: "Compile PHAR for checksum" - working-directory: "compiler/build" - run: "php box.phar compile --no-parallel" - env: - PHAR_CHECKSUM: "1" - COMPOSER_ROOT_VERSION: "2.1.x-dev" - - - name: "Re-sign PHAR" - run: "php compiler/build/resign.php tmp/phpstan.phar" - - - name: "Unset autoloader suffix" - run: "composer config autoloader-suffix --unset" - - - name: "Save checksum" - id: "new_checksum" - run: echo "md5=$(md5sum tmp/phpstan.phar | cut -d' ' -f1)" >> $GITHUB_OUTPUT - - - name: "Assert checksum" - run: | - checksum=${{ steps.info.outputs.checksum }} - new_checksum=${{ steps.new_checksum.outputs.md5 }} - [[ "$checksum" == "$new_checksum" ]]; diff --git a/.github/workflows/phar.yml b/.github/workflows/phar.yml index a468bd523a..2c51d6bbd3 100644 --- a/.github/workflows/phar.yml +++ b/.github/workflows/phar.yml @@ -23,6 +23,7 @@ jobs: outputs: checksum: ${{ steps.checksum.outputs.md5 }} + compiler_changed: ${{ steps.changes.outputs.compiler }} steps: - name: "Checkout" @@ -107,6 +108,15 @@ jobs: - name: "Delete checksum PHAR" run: "rm tmp/phpstan.phar" + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + compiler: + - 'compiler/**' + - '.github/workflows/phar.yml' + - '.github/scripts/**' + integration-tests: if: github.event_name == 'pull_request' needs: compiler-tests @@ -131,6 +141,135 @@ jobs: ref: 2.1.x phar-checksum: ${{needs.compiler-tests.outputs.checksum}} + checksum-phar: + name: "Checksum PHAR" + if: github.event_name == 'pull_request' && needs.compiler-tests.outputs.compiler_changed == 'true' + needs: compiler-tests + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v4 + + - name: Get base commit SHA + id: base + run: echo "base_sha=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT" + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + working-directory: .github/scripts + run: npm ci + + - name: "Compile TS scripts" + working-directory: .github/scripts + run: npx tsc + + - name: Find phar-file-checksum from base commit + id: find-artifact + uses: actions/github-script@v7 + env: + BASE_SHA: ${{ steps.base.outputs.base_sha }} + ARTIFACT_NAME: phar-file-checksum + WORKFLOW_NAME: Compile PHAR + with: + script: | + const script = require('./.github/scripts/dist/find-artifact.js'); + await script({github, context, core}) + + - name: Download old artifact by ID + uses: actions/download-artifact@v4 + with: + artifact-ids: ${{ steps.find-artifact.outputs.artifact_id }} + run-id: ${{ steps.find-artifact.outputs.run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: "Save old checksum" + id: "old_checksum" + run: echo "md5=$(md5sum phar-file-checksum/phpstan.phar | cut -d' ' -f1)" >> $GITHUB_OUTPUT + + - name: "Assert checksum" + run: | + old_checksum=${{ steps.old_checksum.outputs.md5 }} + new_checksum=${{needs.compiler-tests.outputs.checksum}} + [[ "$old_checksum" == "$new_checksum" ]]; + + phar-prefix-diff: + name: "PHAR Prefix Diff" + if: github.event_name == 'pull_request' && needs.compiler-tests.outputs.compiler_changed == 'true' + needs: compiler-tests + runs-on: "ubuntu-latest" + steps: + - uses: actions/checkout@v4 + + - name: Get base commit SHA + id: base + run: echo "base_sha=${{ github.event.pull_request.base.sha }}" >> "$GITHUB_OUTPUT" + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install dependencies + working-directory: .github/scripts + run: npm ci + + - name: "Compile TS scripts" + working-directory: .github/scripts + run: npx tsc + + - name: Find phar-file-checksum from base commit + id: find-artifact + uses: actions/github-script@v7 + env: + BASE_SHA: ${{ steps.base.outputs.base_sha }} + ARTIFACT_NAME: phar-file-checksum + WORKFLOW_NAME: Compile PHAR + with: + script: | + const script = require('./.github/scripts/dist/find-artifact.js'); + await script({github, context, core}) + + # saved to phar-file-checksum/phpstan.phar + - name: Download old artifact by ID + uses: actions/download-artifact@v4 + with: + artifact-ids: ${{ steps.find-artifact.outputs.artifact_id }} + run-id: ${{ steps.find-artifact.outputs.run_id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + # saved to phpstan.phar + - name: "Download phpstan.phar" + uses: actions/download-artifact@v4 + with: + name: phar-file-checksum + + - name: "Install PHP" + uses: "shivammathur/setup-php@v2" + with: + coverage: "none" + php-version: "8.1" + + - name: "Install dependencies" + run: "composer install --no-interaction --no-progress" + + - name: "Extract old phpstan.phar" + run: "php compiler/build/box.phar extract phar-file-checksum/phpstan.phar phar-old" + + - name: "Extract new phpstan.phar" + run: "php compiler/build/box.phar extract phpstan.phar phar-new" + + - name: "List prefix locations in old PHAR" + run: "php .github/scripts/listPrefix.php ${{ github.workspace }}/phar-old > phar-old.txt" + + - name: "List prefix locations in new PHAR" + run: "php .github/scripts/listPrefix.php ${{ github.workspace }}/phar-new > phar-new.txt" + + - name: "Diff locations" + run: "diff -u phar-old.txt phar-new.txt" + commit: name: "Commit PHAR" if: "github.repository_owner == 'phpstan' && (github.ref == 'refs/heads/2.1.x' || startsWith(github.ref, 'refs/tags/'))"