diff --git a/.github/workflows/primer_run_main.yaml b/.github/workflows/primer_run_main.yaml index 22a7976d10..b587bce0fb 100644 --- a/.github/workflows/primer_run_main.yaml +++ b/.github/workflows/primer_run_main.yaml @@ -82,3 +82,15 @@ jobs: with: name: primer_commitstring path: .pylint_primer_tests/commit_string.txt + + # Run primer + - name: Run pylint primer + run: | + . venv/bin/activate + pip install -e . + python tests/primer/primer_tool.py run --type=main + - name: Upload output + uses: actions/upload-artifact@v3 + with: + name: primer_output + path: .pylint_primer_tests/output_main.txt diff --git a/.github/workflows/primer_run_pr.yaml b/.github/workflows/primer_run_pr.yaml index 7b426d5c73..642b34f347 100644 --- a/.github/workflows/primer_run_pr.yaml +++ b/.github/workflows/primer_run_pr.yaml @@ -26,14 +26,16 @@ jobs: steps: - name: Check out code from GitHub uses: actions/checkout@v3.0.2 + with: + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} id: python uses: actions/setup-python@v3.1.2 with: python-version: ${{ matrix.python-version }} - - uses: actions/setup-node@v1 + - uses: actions/setup-node@v3 with: - version: 12 + node-version: 16 - run: npm install @octokit/rest # Restore cached Python environment @@ -62,7 +64,8 @@ jobs: pip install -U -r requirements_test.txt # Cache primer packages - - name: Download diffs + - name: Download last 'main' run info + id: download-main-run uses: actions/github-script@v6 with: script: | @@ -86,6 +89,8 @@ jobs: repo: context.repo.repo, run_id: lastRunMain.id, }); + + // Get commitstring const [matchArtifactMain] = artifacts_main.data.artifacts.filter((artifact) => artifact.name == "primer_commitstring"); const downloadWorkflow = await github.rest.actions.downloadArtifact({ @@ -95,10 +100,24 @@ jobs: archive_format: "zip", }); fs.writeFileSync("primer_commitstring.zip", Buffer.from(downloadWorkflow.data)); + + // Get output + const [matchArtifactMainOutput] = artifacts_main.data.artifacts.filter((artifact) => + artifact.name == "primer_output"); + const downloadWorkflowTwo = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: matchArtifactMainOutput.id, + archive_format: "zip", + }); + fs.writeFileSync("primer_output_main.zip", Buffer.from(downloadWorkflowTwo.data)); + return lastRunMain.head_sha; - name: Copy and unzip the commit string run: | unzip primer_commitstring.zip cp commit_string.txt .pylint_primer_tests/commit_string.txt + - name: Unzip the output of 'main' + run: unzip primer_output_main.zip - name: Get commit string id: commitstring run: | @@ -118,11 +137,37 @@ jobs: . venv/bin/activate python tests/primer/primer_tool.py prepare --check + # Merge the 'main' commit of last successful run + - name: Pull 'main' + shell: bash + run: | + git config --global user.email "primer@example.com" + git config --global user.name "Pylint Primer" + git pull origin ${{ steps.download-main-run.outputs.result }} --no-edit --no-commit --no-rebase + + # Run primer + - name: Run pylint primer + run: | + . venv/bin/activate + pip install -e . + python tests/primer/primer_tool.py run --type=pr + - name: Upload output of PR + uses: actions/upload-artifact@v3 + with: + name: primer_output_pr + path: .pylint_primer_tests/output_pr.txt + - name: Upload output of 'main' + uses: actions/upload-artifact@v3 + with: + name: primer_output_main + path: output_main.txt + + # Save PR number so we know which PR to comment on - name: Save PR number run: | echo ${{ github.event.pull_request.number }} | tee pr_number.txt - name: Upload PR number - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: primer_pylint_output_workflow path: pr_number.txt diff --git a/tests/primer/packages_to_prime.json b/tests/primer/packages_to_prime.json index 8051845cd4..a384598fc0 100644 --- a/tests/primer/packages_to_prime.json +++ b/tests/primer/packages_to_prime.json @@ -2,7 +2,8 @@ "astroid": { "branch": "main", "directories": ["astroid"], - "url": "https://github.com/PyCQA/astroid" + "url": "https://github.com/PyCQA/astroid", + "pylintrc_relpath": "pylintrc" }, "black": { "branch": "main", diff --git a/tests/primer/primer_tool.py b/tests/primer/primer_tool.py index 6bd994249c..4d40cb2afa 100644 --- a/tests/primer/primer_tool.py +++ b/tests/primer/primer_tool.py @@ -6,10 +6,13 @@ import argparse import json +from io import StringIO from pathlib import Path import git +from pylint.lint import Run +from pylint.reporters import JSONReporter from pylint.testutils.primer import PackageToLint MAIN_DIR = Path(__file__).parent.parent.parent @@ -49,6 +52,12 @@ def __init__(self, json_path: Path) -> None: default=False, ) + # All arguments for the run parser + run_parser = self._subparsers.add_parser("run") + run_parser.add_argument( + "--type", choices=["main", "pr"], required=True, help="Type of primer run." + ) + # Storing arguments self.config = self._argument_parser.parse_args() @@ -58,6 +67,8 @@ def __init__(self, json_path: Path) -> None: def run(self) -> None: if self.config.command == "prepare": self._handle_prepare_command() + if self.config.command == "run": + self._handle_run_command() def _handle_prepare_command(self) -> None: commit_string = "" @@ -88,6 +99,32 @@ def _handle_prepare_command(self) -> None: ) as f: f.write(commit_string) + def _handle_run_command(self) -> None: + packages: dict[str, list[dict[str, str | int]]] = {} + + for package, data in self.packages.items(): + output = self._lint_package(data) + packages[package] = output + print(f"Successfully primed {package}.") + + with open( + PRIMER_DIRECTORY / f"output_{self.config.type}.txt", "w", encoding="utf-8" + ) as f: + json.dump(packages, f) + + def _lint_package(self, data: PackageToLint) -> list[dict[str, str | int]]: + # We want to test all the code we can + enables = ["--enable-all-extensions", "--enable=all"] + # Duplicate code takes too long and is relatively safe + disables = ["--disable=duplicate-code"] + arguments = data.directories + data.pylint_args + enables + disables + if data.pylintrc_relpath: + arguments += [f"--rcfile={data.pylintrc_relpath}"] + output = StringIO() + reporter = JSONReporter(output) + Run(arguments, reporter=reporter, do_exit=False) + return json.loads(output.getvalue()) + @staticmethod def _get_packages_to_lint_from_json(json_path: Path) -> dict[str, PackageToLint]: with open(json_path, encoding="utf8") as f: