-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[Bot] Add prdoc generation #5331
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| #!/usr/bin/env python3 | ||
|
|
||
| """ | ||
| Generate the PrDoc for a Pull Request with a specific number, audience and bump level. | ||
|
|
||
| It downloads and parses the patch from the GitHub API to opulate the prdoc with all modified crates. | ||
| This will delete any prdoc that already exists for the PR if `--force` is passed. | ||
|
|
||
| Usage: | ||
| python generate-prdoc.py --pr 1234 --audience "TODO" --bump "TODO" | ||
| """ | ||
|
|
||
| import argparse | ||
| import os | ||
| import re | ||
| import sys | ||
| import subprocess | ||
| import toml | ||
| import yaml | ||
| import requests | ||
|
|
||
| from github import Github | ||
| import whatthepatch | ||
| from cargo_workspace import Workspace | ||
|
|
||
| # Download the patch and pass the info into `create_prdoc`. | ||
| def from_pr_number(n, audience, bump, force): | ||
| print(f"Fetching PR '{n}' from GitHub") | ||
| g = Github() | ||
|
|
||
| repo = g.get_repo("paritytech/polkadot-sdk") | ||
| pr = repo.get_pull(n) | ||
|
|
||
| patch_url = pr.patch_url | ||
| patch = requests.get(patch_url).text | ||
|
|
||
| create_prdoc(n, audience, pr.title, pr.body, patch, bump, force) | ||
|
|
||
| def create_prdoc(pr, audience, title, description, patch, bump, force): | ||
| path = f"prdoc/pr_{pr}.prdoc" | ||
|
|
||
| if os.path.exists(path): | ||
| if force == True: | ||
| print(f"Overwriting existing PrDoc for PR {pr}") | ||
| else: | ||
| print(f"PrDoc already exists for PR {pr}. Use --force to overwrite.") | ||
| sys.exit(1) | ||
| else: | ||
| print(f"No preexisting PrDoc for PR {pr}") | ||
|
|
||
| prdoc = { "doc": [{}], "crates": [] } | ||
|
|
||
| prdoc["title"] = title | ||
| prdoc["doc"][0]["audience"] = audience | ||
| prdoc["doc"][0]["description"] = description | ||
|
|
||
| workspace = Workspace.from_path(".") | ||
|
|
||
| modified_paths = [] | ||
| for diff in whatthepatch.parse_patch(patch): | ||
| modified_paths.append(diff.header.new_path) | ||
|
|
||
| modified_crates = {} | ||
| for p in modified_paths: | ||
| # Go up until we find a Cargo.toml | ||
| p = os.path.join(workspace.path, p) | ||
| while not os.path.exists(os.path.join(p, "Cargo.toml")): | ||
| p = os.path.dirname(p) | ||
|
|
||
| with open(os.path.join(p, "Cargo.toml")) as f: | ||
| manifest = toml.load(f) | ||
|
|
||
| if not "package" in manifest: | ||
| print(f"File was not in any crate: {p}") | ||
| continue | ||
|
|
||
| crate_name = manifest["package"]["name"] | ||
| if workspace.crate_by_name(crate_name).publish: | ||
| modified_crates[crate_name] = True | ||
| else: | ||
| print(f"Skipping unpublished crate: {crate_name}") | ||
|
|
||
| print(f"Modified crates: {modified_crates.keys()}") | ||
|
|
||
| for crate_name in modified_crates.keys(): | ||
| entry = { "name": crate_name } | ||
|
|
||
| if bump == 'silent' or bump == 'ignore' or bump == 'no change': | ||
| entry["validate"] = False | ||
| else: | ||
| entry["bump"] = bump | ||
|
|
||
| print(f"Adding crate {entry}") | ||
| prdoc["crates"].append(entry) | ||
|
|
||
| # write the parsed PR documentation back to the file | ||
| with open(path, "w") as f: | ||
| yaml.dump(prdoc, f) | ||
|
|
||
| def parse_args(): | ||
| parser = argparse.ArgumentParser() | ||
| parser.add_argument("--pr", type=int, required=True) | ||
| parser.add_argument("--audience", type=str, default="TODO") | ||
| parser.add_argument("--bump", type=str, default="TODO") | ||
| parser.add_argument("--force", type=str) | ||
| return parser.parse_args() | ||
|
|
||
| if __name__ == "__main__": | ||
| args = parse_args() | ||
| force = True if args.force.lower() == "true" else False | ||
| print(f"Args: {args}, force: {force}") | ||
| from_pr_number(args.pr, args.audience, args.bump, force) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,78 @@ | ||
| name: Command PrDoc | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| pr: | ||
| type: number | ||
| description: Number of the Pull Request | ||
| required: true | ||
| bump: | ||
| type: choice | ||
| description: Default bump level for all crates | ||
| default: "TODO" | ||
| required: true | ||
| options: | ||
| - "TODO" | ||
| - "no change" | ||
| - "patch" | ||
| - "minor" | ||
| - "major" | ||
| audience: | ||
| type: choice | ||
| description: Audience of the PrDoc | ||
| default: "TODO" | ||
| required: true | ||
| options: | ||
| - "TODO" | ||
| - "Runtime Dev" | ||
| - "Runtime User" | ||
| - "Node Dev" | ||
| - "Node User" | ||
| overwrite: | ||
| type: choice | ||
| description: Overwrite existing PrDoc | ||
| default: "true" | ||
| required: true | ||
| options: | ||
| - "true" | ||
| - "false" | ||
|
|
||
| concurrency: | ||
| group: command-prdoc | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| cmd-prdoc: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| steps: | ||
| - name: Download repo | ||
| uses: actions/checkout@v4 | ||
| - name: Install gh cli | ||
| id: gh | ||
| uses: ./.github/actions/set-up-gh | ||
| with: | ||
| pr-number: ${{ inputs.pr }} | ||
| GH_TOKEN: ${{ github.token }} | ||
| - name: Generate PrDoc | ||
| run: | | ||
| python3 -m pip install -q cargo-workspace PyGithub whatthepatch pyyaml toml | ||
|
|
||
| python3 .github/scripts/generate-prdoc.py --pr "${{ inputs.pr }}" --bump "${{ inputs.bump }}" --audience "${{ inputs.audience }}" --force "${{ inputs.overwrite }}" | ||
|
Contributor
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. may be you could also alternatively add an option to start it with command? issue_comment: # listen for comments on issues
types: [created]Or I will do later for all
Member
Author
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. I have a But i would also prefer comments, as outsiders can probably not run CI actions. Not sure why the comment approach was deprecated?
Contributor
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. it wasn't deprecated, we just tried to move to GHA faster/cheaper, and that was one of the fast and secure ways |
||
|
|
||
| - name: Report failure | ||
| if: ${{ failure() }} | ||
| run: gh pr comment ${{ inputs.pr }} --body "<h2>Command failed ❌</h2> Run by @${{ github.actor }} for <code>${{ github.workflow }}</code> failed. See logs <a href=\"$RUN\">here</a>." | ||
| env: | ||
| RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} | ||
| GH_TOKEN: ${{ github.token }} | ||
| - name: Push Commit | ||
| uses: stefanzweifel/git-auto-commit-action@v5 | ||
| with: | ||
| commit_message: Add PrDoc (auto generated) | ||
| branch: ${{ steps.gh.outputs.branch }} | ||
| file_pattern: 'prdoc/*.prdoc' | ||
Uh oh!
There was an error while loading. Please reload this page.