-
-
Notifications
You must be signed in to change notification settings - Fork 1
playwright bot #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
+4,282
−153
Closed
playwright bot #14
Changes from all commits
Commits
Show all changes
64 commits
Select commit
Hold shift + click to select a range
95f1e1e
use uv and githubkit
JacobCoffee f7bcbe3
add playwright basic
JacobCoffee 7944e6b
remove stringent patch version
JacobCoffee 4dc9eae
playwright initial base + otp
JacobCoffee 92a4732
playwright comment grab
JacobCoffee a1e3a58
add post comments
JacobCoffee d301cfa
organize things into module, merge comments tests
JacobCoffee b9882f7
fix missing f
JacobCoffee c928c22
add helpers
JacobCoffee 8061f44
add monitoring ci
JacobCoffee 7fa9d3b
placeholder for playright things
JacobCoffee b9d1144
set username inside clien
JacobCoffee 09b2a13
parse comments as commands
JacobCoffee a629854
idea file
JacobCoffee 09210f5
run linting with rules actually enabled
JacobCoffee 6a2f794
add some quick targets for local dev
JacobCoffee 4534192
lint
JacobCoffee 2789d28
add gha
JacobCoffee 1cd9515
source state for exampl
JacobCoffee 80ccdd6
lint
JacobCoffee f0c33b0
placeholder file
JacobCoffee 7463115
dont process bot comments
JacobCoffee 75119c9
dont print but log
JacobCoffee cc11440
swap to log instead of print, run lint/fmt
JacobCoffee a1a6575
update tests pasing, source tests for new files,
JacobCoffee 05283d8
add some info to help people onboard
JacobCoffee 03bac83
add words
JacobCoffee a6c498e
fix spacing
JacobCoffee 2c5d40f
spelling...
JacobCoffee a772d26
we have cron-run that is more clear
JacobCoffee f820090
more docs for weirdness
JacobCoffee f568fae
EVEN MORE docs on clarifying weirdness and requirements
JacobCoffee 8714967
update makefile section printouts
JacobCoffee f836ebd
address comments
JacobCoffee d20a309
address comments
JacobCoffee dcb77e2
address comments
JacobCoffee 263c50e
simplify, remove unused call on enumerate
JacobCoffee 182ddee
enable health check
JacobCoffee 1a72dbd
remove unused noqa
JacobCoffee a6df710
configify slugs, change workflows
JacobCoffee 2ea402a
make bootstrap org private
JacobCoffee 4c57133
move commands into another branch
JacobCoffee b4238fb
wrap in run load in try/exc
JacobCoffee fa408e0
why be fancy? no names pls!
JacobCoffee 7924a12
make fixture out of large pytest skipif
JacobCoffee cd82f98
refactor health check to use new status tracking
JacobCoffee f482e9b
piece out integration test
JacobCoffee 881ca22
clean up unit tests
JacobCoffee a14dd6f
clean up unit tests
JacobCoffee 4d68d43
move conf into one area,
JacobCoffee d135bd3
fmt
JacobCoffee 14e3dc3
elevate to globals
JacobCoffee a5c7463
make tests pass
JacobCoffee 16444ac
Add bot commands
JacobCoffee e3f9782
Add “Act” for local GitHub Actions debugging
JacobCoffee 76ff3a0
fix bot author check
JacobCoffee b8c82b3
fix default for bot uname
JacobCoffee e510788
fix: raise error instead of returning fallback timestamp
JacobCoffee a3e50f0
fmt
JacobCoffee e4eca8c
fix lint, none checks on username for bot
JacobCoffee cd2a22d
move from parsed_data to json because githubkit but with pydnatic
JacobCoffee 2b64e6c
move from parsed_data to json because githubkit but with pydnatic
JacobCoffee f76e513
update tests
JacobCoffee 3cdb4d7
toggleable commenting
JacobCoffee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,20 @@ | ||
| # GitHub App credentials (for API-capable operations) | ||
| GH_CLIENT_ID="123456" | ||
| GH_CLIENT_PRIVATE_KEY="base64...your...pem...keyfile" | ||
| GH_AUTH_TOKEN="ghp_123456" | ||
|
|
||
| # Playwright bot credentials (for browser automation) | ||
| GH_BOT_USERNAME=PSRT-GHSA-Automation | ||
| GH_BOT_PASSWORD=<secure-password> | ||
| GH_BOT_OTP_SECRET=<optional-2fa-secret> # Key used to generate OTP codes | ||
|
|
||
| # CVE API credentials | ||
| CVE_USERNAME="user@example.org" | ||
| CVE_API_KEY="123456" | ||
| CVE_ENV="testproddev" | ||
|
|
||
| # Sentry | ||
| SENTRY_DSN= | ||
|
|
||
| # Set to "true" to disable comment posting (staging/testing mode) | ||
| DONT_COMMENT=false |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| name: "PSRT GHSA Bot" | ||
| name: "PSRT GHSA Cron Bot" | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| name: "Health Check" | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| - cron: "15 * * * *" | ||
|
|
||
| jobs: | ||
| monitor: | ||
| runs-on: ubuntu-latest | ||
| name: "Monitor Workflow Health" | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
|
|
||
| - name: Set up uv | ||
| uses: astral-sh/setup-uv@v6 | ||
| with: | ||
| enable-cache: true | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v6 | ||
| with: | ||
| python-version-file: "pyproject.toml" | ||
|
|
||
| - name: Install dependencies | ||
| run: uv sync --locked --no-editable --no-dev | ||
|
|
||
| - name: Check workflow status and report to Sentry | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| SENTRY_DSN: ${{ secrets.SENTRY_DSN }} | ||
| GITHUB_REPOSITORY: ${{ github.repository }} | ||
| run: uv run python src/psrt_ghsa_bot/health_check.py |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| name: "PSRT GHSA Playwright Bot" | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| schedule: | ||
| - cron: "*/5 * * * *" | ||
|
|
||
| jobs: | ||
| process-comments: | ||
| runs-on: ubuntu-latest | ||
| name: "Process GHSA Comments" | ||
| steps: | ||
| - uses: actions/checkout@v5 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Set up uv | ||
| uses: astral-sh/setup-uv@v6 | ||
| with: | ||
| enable-cache: true | ||
|
|
||
| - name: Set up Python | ||
| uses: actions/setup-python@v6 | ||
| with: | ||
| python-version-file: "pyproject.toml" | ||
|
|
||
| - name: Install dependencies | ||
| run: uv sync --locked --no-editable --no-dev | ||
|
|
||
| - name: Install Playwright browsers | ||
| run: uv run playwright install --with-deps chromium | ||
|
|
||
| - name: Restore state from cache | ||
| id: cache-state | ||
| uses: actions/cache/restore@v4 | ||
| with: | ||
| path: state.json | ||
| key: playwright-state-${{ github.run_id }} | ||
| restore-keys: | | ||
| playwright-state- | ||
|
|
||
| - name: Process comments | ||
| run: uv run python -m psrt_ghsa_bot.comment_processor | ||
| env: | ||
| GH_CLIENT_ID: ${{ vars.GH_CLIENT_ID }} | ||
| GH_CLIENT_SECRET: ${{ secrets.GH_CLIENT_SECRET }} | ||
| GH_CLIENT_PRIVATE_KEY: ${{ secrets.GH_CLIENT_PRIVATE_KEY }} | ||
| CVE_USERNAME: ${{ vars.CVE_USERNAME }} | ||
| CVE_API_KEY: ${{ secrets.CVE_API_KEY }} | ||
| CVE_ENV: ${{ vars.CVE_ENV }} | ||
| GH_BOT_USERNAME: ${{ vars.GH_BOT_USERNAME }} | ||
| GH_BOT_PASSWORD: ${{ secrets.GH_BOT_PASSWORD }} | ||
| GH_BOT_OTP_SECRET: ${{ secrets.GH_BOT_OTP_SECRET }} | ||
|
|
||
| - name: Save state to cache | ||
| if: always() | ||
| uses: actions/cache/save@v4 | ||
| with: | ||
| path: state.json | ||
| key: playwright-state-${{ github.run_id }} | ||
|
|
||
| - name: Commit state file | ||
| if: always() | ||
| run: | | ||
| git config user.name "PSRT-GHSA-Automation[bot]" | ||
| git config user.email "bot@python.org" | ||
| git add state.json | ||
| git diff --quiet || git commit -m "Update comment processing state [skip ci]" | ||
| git push || true | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,83 @@ | ||
| # PSRT GHSA Bot | ||
|
|
||
| Bot which adds the PSRT GitHub team (`python/psrt`) and CVE IDs to GitHub Security Advisories. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### GitHub Actions | ||
|
|
||
| - The cron bot runs off of [`.github/workflows/cron.yml`](.github/workflows/cron.yml) and runs at the top of each hour. | ||
| - Calls [src/psrt_ghsa_bot/app.py](src/psrt_ghsa_bot/app.py) | ||
| - Fetches open GHSAs from all installed orgs/repos | ||
| - Adds PSRT team to GHSAs without it | ||
| - Assigns CVE IDs to draft GHSAs without one | ||
| - The Playwright bot runs off of [`.github/workflows/playwright.yml`](.github/workflows/playwright.yml) and runs every 5 minutes. | ||
| - Calls [src/psrt_ghsa_bot/comment_processor.py](src/psrt_ghsa_bot/comment_processor.py) | ||
| - Reads GHSA comments via Playwright (no API available) | ||
| - Parses `@<bot-username>` commands, executes if authorized | ||
| - Posts responses, tracks state in `state.json` | ||
| - Health checks are done via [`.github/workflows/health-check.yml`](.github/workflows/health-check.yml) and runs every 15 minutes. | ||
| - It checks the status using the `gh` CLI and reports to Sentry if the bot is not healthy via Sentry cron monitors. | ||
|
|
||
| ### Why Playwright? | ||
|
|
||
| The GHSA API is limited and has not really been developed in awhile. As such, it is missing a lot of features | ||
| like: | ||
| - Commenting on GHSAs | ||
| - Adding teams to GHSAs | ||
| - Assigning CVE IDs to GHSAs | ||
| - Removing temporary forks generated inside a GHSA that collaborators use fro remediation | ||
| - No webhooks to respond to things.. so we do the GHA polling thing... | ||
|
|
||
| That's why there is this weird split between the cron.yml and playwright.yml. As API things | ||
| are added, we can move more into app.py/cron.yml and remove the playwright stuff (gladly!) | ||
|
|
||
| ## Installation | ||
|
|
||
| The GitHub app (API-related activities) **MUST** be installed in all GitHub organizations | ||
| you want scanned. The GitHub user (`GH_BOT_USERNAME`, used by Playwright) **MUST** have access to the repos that | ||
| you want to interact with. | ||
|
|
||
| **Important:** The GitHub App installation and GitHub user require the same permissions on repositories. | ||
| The Playwright bot uses the GitHub App installation to generate a list of repos | ||
| (~[comment_processor.py:130-140](src/psrt_ghsa_bot/comment_processor.py#L130-L140)), so any permission | ||
| mismatch will cause failures | ||
|
|
||
|
|
||
| ## Development | ||
|
|
||
| Uses `uv` for dependency management and `pytest` for testing. | ||
|
|
||
| ### Setup | ||
|
|
||
| Make sure you have `uv` installed at https://docs.astral.sh/uv/getting-started/installation/ | ||
| Quickly, for Linux/macOS: | ||
| ```shell | ||
| curl -LsSf https://astral.sh/uv/install.sh | sh | ||
| ``` | ||
| or (not recommended): | ||
| ```shell | ||
| pipx install uv | ||
| ``` | ||
|
|
||
| Afterwards, you can use `make` to run the commands in the [`Makefile`](Makefile). | ||
| - `make upgrade` - Upgrade all dependencies to the latest stable versions. | ||
|
|
||
| Every time you run `uv run` or anything it automatically installs/syncs the dependencies | ||
| and it's near-instant so there is no `make install` or anything. | ||
|
|
||
| ### Tests | ||
|
|
||
| Only unique things here are `PLAYWRIGHT_FULL.test`, which can can see more about in [`PLAYWRIGHT_FULL.test.example`](tests/PLAYWRIGHT_FULL.test.example). | ||
| This just tells the [`Makefile`](Makefile) target `make test` to run `playwright install` before running the tests | ||
| and then enables some of the skipped tests. These tests assume a test organization and all the setup behind that | ||
| because it is an integration test and will comment on and read a GHSA advisory. | ||
|
|
||
| ### Scripts | ||
|
|
||
| There is a [`scripts/`](scripts/) directory with some local dev scripts, namely one that will | ||
| set up an organization with all the things needed to develop (TODO: it doesn't actually do anything yet.) | ||
|
|
||
| The idea behind the bootstrap_org.py is that it will: | ||
| - Take your test org, set up a `psrt` (or whatever) team, create a repo with some GHSA, then comment, read the comments, etc. | ||
| This helps more from the integration testing side of things without doing it all in some public, busy repo like `python/CPython` :) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7,8 +7,12 @@ requires-python = ">=3.14.0" | |||||
| dependencies = [ | ||||||
| "cvelib>=1.4.0", | ||||||
| "githubkit[auth-app]>=0.13.5", | ||||||
| # we might could put this into a dep group to not load it every time we install | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| # inside gh actions for cron.yml or the sentry check in | ||||||
| "playwright>=1.55.0", | ||||||
| "pyotp>=2.9.0", | ||||||
| "python-dotenv>=1.0.0", | ||||||
| "sentry-sdk>=2.22.0", | ||||||
| ] | ||||||
|
|
||||||
| [dependency-groups] | ||||||
|
|
@@ -32,11 +36,67 @@ line-length = 120 | |||||
| indent-width = 4 | ||||||
|
|
||||||
| [tool.ruff.lint] | ||||||
| ignore = ["D203", "D213", "COM812"] | ||||||
| select = ["ALL"] | ||||||
| ignore = [ | ||||||
| "D203", | ||||||
| "D213", | ||||||
| "COM812", | ||||||
| "T201", | ||||||
| "TD", # todo without author | ||||||
| "FIX002", # Line contains TODO | ||||||
| "PLR0913", # Too many arguments | ||||||
| "PLR0911", # Too many returns | ||||||
| "C901", # Too complex | ||||||
| "ARG001", # unused arg | ||||||
| "BLE001", # blind except | ||||||
| ] | ||||||
|
|
||||||
| [tool.ruff.format] | ||||||
| quote-style = "double" | ||||||
| indent-style = "space" | ||||||
|
|
||||||
| [tool.ruff.lint.per-file-ignores] | ||||||
| "tests/**/*.*" = [ | ||||||
| "A", | ||||||
| "ARG", | ||||||
| "B", | ||||||
| "BLE", | ||||||
| "C901", | ||||||
| "D", | ||||||
| "DTZ", | ||||||
| "EM", | ||||||
| "FBT", | ||||||
| "G", | ||||||
| "N", | ||||||
| "PGH", | ||||||
| "PIE", | ||||||
| "PLR", | ||||||
| "PLW", | ||||||
| "PTH", | ||||||
| "RSE", | ||||||
| "S", | ||||||
| "S101", | ||||||
| "SIM", | ||||||
| "TC", | ||||||
| "TRY", | ||||||
| "SLF", | ||||||
| "ANN", | ||||||
| "FIX", | ||||||
| "TD", | ||||||
| "ERA", | ||||||
| ] | ||||||
| "scripts/**/*.*" = [ | ||||||
| "INP001", # Implicit namespace package | ||||||
| "EXE001", # Shebang not executable | ||||||
| "RUF001", # Ambiguous unicode | ||||||
| "DTZ", # Timezone issues | ||||||
| "S", # Security issues | ||||||
| "T201", # Print statements | ||||||
| ] | ||||||
|
|
||||||
| [tool.ruff.lint.pydocstyle] | ||||||
| convention = "google" | ||||||
|
|
||||||
| [tool.pytest.ini_options] | ||||||
| addopts = "-p no:anyio" | ||||||
| testpaths = ["tests/unit"] | ||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1 @@ | ||||||
| """Scripts for PSRT GHSA bot.""" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just speculation, but might this introduce a race condition?