Skip to content

feat: add scheduled workflow to sync Paragon icon allow-list - #537

Open
carlos-marquez-wgu wants to merge 3 commits into
openedx:mainfrom
WGU-Open-edX:carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list
Open

carlos-marquez-wgu wants to merge 3 commits into
openedx:mainfrom
WGU-Open-edX:carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list

Conversation

@carlos-marquez-wgu

@carlos-marquez-wgu carlos-marquez-wgu commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Add a weekly GitHub Actions workflow that checks if the @openedx/paragon version used by frontend-app-admin-console has changed, and if so, updates the pinned version and regenerates the vendored icon allow-list via make paragon_icons, then opens a PR with the changes.

Its set to run automatically weekly, at 00:00 on Monday. (let me know if you want a difference cadence, I am re-using the same one of this other action -> https://github.com/openedx/openedx-authz/blob/main/.github/workflows/upgrade-python-requirements.yml)

Refs: ADR-0029

Testing evidence

I forked this repo to my personal account and run the workflow there

Successful workflow run: https://github.com/carlos-marquez-wgu/openedx-authz/actions/runs/39295926719
Here is the PR it created: carlos-marquez-wgu#4

Testing instructions

  1. Fork the repo: https://github.com/openedx/openedx-authz
  2. Clone the new fork to your local machine
  3. Setup additional remote in your local copy
git remote add wgu git@github.com:WGU-Open-edX/openedx-authz.git
  1. Pull this PR tag:
git fetch wgu
git checkout carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list
  1. Push the branch to your fork
# note: change `origin` remote for the remote you are using for your fork if needed
git push -u origin carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list
  1. In your fork, change default branch to carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list temporarily, this way the workflow will appear in the Actions tab
  2. Allow actions to create PRs, go to Settings → Actions → General → Workflow permissions
    Check the box: "Allow GitHub Actions to create and approve pull requests"
  3. Go to Actions tab in your repo, and run your workflow
  4. Verify the workflow ran successfully and a PR was created (see Testing evidence above for an example of how it looks)

Run:
image

PR:
image

Concerns

With the GITHUB_TOKEN used, the PR needs a maintainer to run the CI workflows

image

We will need a PAT token to make it work, I see the workflow at openedx-authz/.github/workflows/upgrade-python-requirements.yml has the token secrets.REQUIREMENTS_BOT_GITHUB_TOKEN, seems this is a valid PAT we can re-use, but wanted maintainers confirmation / direction before using this one, keep the standard GITHUB_TOKEN, create a new PAT for this, or something else. Let me know what you think is best!

Merge checklist:
Check off if complete or not applicable:

  • Documentation updated (not only docstrings)
  • Fixup commits are squashed away
  • Unit tests added/updated
  • Manual testing instructions provided
  • Noted any: Concerns, dependencies, migration issues, deadlines, tickets

AI Usage

Kiro + Claude were used to assist with the creation of the github workflow implementations while throughly and carefully guided, everything was reviewed and corrected manually by an actual person and ensured the changes were up to standard and met the closing issue requirements.

Closes: #528

@openedx-webhooks openedx-webhooks added the open-source-contribution PR author is not from Axim or 2U label Oct 15, 2026
@openedx-webhooks

openedx-webhooks commented Oct 15, 2026 •

Copy link
Copy Markdown

Thanks for the pull request, @carlos-marquez-wgu!

This repository is currently maintained by @openedx/committers-openedx-authz.

Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review.

🔘 Get product approval

If you haven't already, check this list to see if your contribution needs to go through the product review process.

  • If it does, you'll need to submit a product proposal for your contribution, and have it reviewed by the Product Working Group.
    • This process (including the steps you'll need to take) is documented here.
  • If it doesn't, simply proceed with the next step.
🔘 Provide context

To help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:

  • Dependencies

    This PR must be merged before / after / at the same time as ...

  • Blockers

    This PR is waiting for OEP-1234 to be accepted.

  • Timeline information

    This PR must be merged by XX date because ...

  • Partner information

    This is for a course on edx.org.

  • Supporting documentation
  • Relevant Open edX discussion forum threads
🔘 Get a green build

If one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green.

Details
Where can I find more information?

If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources:

When can I expect my changes to be merged?

Our goal is to get community contributions seen and reviewed as efficiently as possible.

However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:

  • The size and impact of the changes that it introduces
  • The need for product review
  • Maintenance status of the parent repository

💡 As a result it may take up to several weeks or months to complete a review and merge your PR.

@github-project-automation github-project-automation Bot moved this to Needs Triage in Contributions Oct 15, 2026
@carlos-marquez-wgu
carlos-marquez-wgu force-pushed the carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list branch from e5f59bc to c41f116 Compare October 15, 2026 22:28
@carlos-marquez-wgu carlos-marquez-wgu changed the title ci: add scheduled workflow to sync Paragon icon allow-list feat: add scheduled workflow to sync Paragon icon allow-list Oct 15, 2026
@carlos-marquez-wgu
carlos-marquez-wgu marked this pull request as ready for review October 16, 2026 20:43
@carlos-marquez-wgu

Copy link
Copy Markdown
Contributor Author

Hi @openedx/committers-openedx-authz, this PR is ready for reviews

@rodmgwgu rodmgwgu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, just I think we should get the actual paragon version from package-lock.json instead.

We will need a PAT token to make it work, I see the workflow at openedx-authz/.github/workflows/upgrade-python-requirements.yml has the token secrets.REQUIREMENTS_BOT_GITHUB_TOKEN, seems this is a valid PAT we can re-use, but wanted maintainers confirmation / direction before using this one, keep the standard GITHUB_TOKEN, create a new PAT for this, or something else. Let me know what you think is best!

On the Github token conversation, I don't know what's the correct way forward, @mariajgrimaldi @bmtcril do you know if we need to request a new token for that?

id: upstream
run: |
range=$(curl -fsSL \
https://raw.githubusercontent.com/openedx/frontend-app-admin-console/master/package.json \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to check against the package-lock.json to get the actual specific version being installed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea! I made the change, this is the new command getting the version from package-lock.json

curl -fsSL \
            https://raw.githubusercontent.com/openedx/frontend-app-admin-console/master/package-lock.json \
            | jq -r '.packages["node_modules/@openedx/paragon"].version'
23.23.0

I updated the PR description with new examples (workflow run and pr) after the changes :)

Add a weekly GitHub Actions workflow that checks if the @openedx/paragon
version used by frontend-app-admin-console has changed, and if so,
updates the pinned version and regenerates the vendored icon allow-list
via `make paragon_icons`, then opens a PR with the changes.

Refs: ADR 0029
@carlos-marquez-wgu
carlos-marquez-wgu force-pushed the carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list branch from c41f116 to 8b0542e Compare October 19, 2026 17:46

@rodmgwgu rodmgwgu left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! just the token decision remains pending.

@bmtcril bmtcril left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this, and for the thorough testing notes! On the token question, I'd prefer we not use a PAT here. I think we can get CI running on the bot PR with the default GITHUB_TOKEN.

PRs opened with GITHUB_TOKEN don't fire pull_request workflows, but GitHub explicitly exempts workflow_dispatch and repository_dispatch from that rule. So the workflow can open the PR and then dispatch ci.yml against the bot branch. Those runs are against the PR's head commit, so the checks show up on the PR under the same job names and branch protection should still work.

The steps would be:

  1. Add workflow_dispatch: to the on: block in ci.yml.
  2. In this workflow, add actions: write to permissions, give the create-pull-request step id: cpr, and add a step after it:
      - name: Trigger CI on the bot branch
        if: steps.cpr.outputs.pull-request-operation == 'created' || steps.cpr.outputs.pull-request-operation == 'updated'
        env:
          GH_TOKEN: ${{ github.token }}
        run: gh workflow run ci.yml --ref bot/sync-paragon-icons

If that makes sense could you try that in your fork and confirm the checks attach to the PR?

- cron: "0 0 * * 1"
workflow_dispatch:

permissions:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed for the CI dispatch suggested in the top-level comment:

permissions:
  contents: write
  pull-requests: write
  actions: write

sync-paragon-icons:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please pin all of the required actions to SHAs and make sure they're at the latest versions?

run: |
version=$(curl -fsSL \
https://raw.githubusercontent.com/openedx/frontend-app-admin-console/master/package-lock.json \
| jq -r '.packages["node_modules/@openedx/paragon"].version')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value comes from a file in another repo and is later expanded with ${{ }} directly into run: scripts and sed, in a job that has contents: write. It's lower risk since it's an openedx repo, but it's an injection path. Could we validate it right here and fail otherwise? Something like...

if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
  echo "Unexpected Paragon version: '$version'" >&2
  exit 1
fi

- name: Compare versions
id: compare
run: |
current="${{ steps.current.outputs.version }}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to the note on line 34: step outputs should be passed through env: instead of being expanded inline in the script. Something like:

        env:
          CURRENT: ${{ steps.current.outputs.version }}
          UPSTREAM: ${{ steps.upstream.outputs.version }}
        run: |
          if [ "$CURRENT" = "$UPSTREAM" ]; then

The same applies to new_version on line 54.

if: steps.compare.outputs.changed == 'true'
run: make paragon_icons

- name: Verify regenerated list

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This runs immediately after make paragon_icons, so I don't see how it can't fail. I think it can be dropped since CI will run on the PR once the dispatch step is in.


- name: Create Pull Request
if: steps.compare.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v8.1.1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pin this to a commit SHA as well, and add id: cpr so the CI dispatch step can read pull-request-operation.

if: steps.compare.outputs.changed == 'true'
uses: peter-evans/create-pull-request@v8.1.1
with:
token: ${{ secrets.GITHUB_TOKEN }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the default, so it can be removed.

- Pin actions to SHAs
- Add 'actions: write'
- Validate version semver with a regex
- Pass outputs through env
- Drop redundant 'paran_icons_check'
- Add id: cpr to create-pull-request
- Remove default token statement
- Added workflow_dispatch ti ci.yml
- Trigger github workflow run on pr
@carlos-marquez-wgu
carlos-marquez-wgu force-pushed the carlos-marquez-wgu/issue-528-scheduled-job-update-paragon-icons-list branch from 6b98009 to d008421 Compare October 22, 2026 16:44
@mphilbrick211 mphilbrick211 added the mao-onboarding Reviewing this will help onboard devs from an Axim mission-aligned organization (MAO). label Oct 22, 2026
@mphilbrick211 mphilbrick211 moved this from Needs Triage to In Eng Review in Contributions Oct 22, 2026
@carlos-marquez-wgu

Copy link
Copy Markdown
Contributor Author

Thanks for this, and for the thorough testing notes! On the token question, I'd prefer we not use a PAT here. I think we can get CI running on the bot PR with the default GITHUB_TOKEN.

PRs opened with GITHUB_TOKEN don't fire pull_request workflows, but GitHub explicitly exempts workflow_dispatch and repository_dispatch from that rule. So the workflow can open the PR and then dispatch ci.yml against the bot branch. Those runs are against the PR's head commit, so the checks show up on the PR under the same job names and branch protection should still work.

The steps would be:

  1. Add workflow_dispatch: to the on: block in ci.yml.
  2. In this workflow, add actions: write to permissions, give the create-pull-request step id: cpr, and add a step after it:
      - name: Trigger CI on the bot branch
        if: steps.cpr.outputs.pull-request-operation == 'created' || steps.cpr.outputs.pull-request-operation == 'updated'
        env:
          GH_TOKEN: ${{ github.token }}
        run: gh workflow run ci.yml --ref bot/sync-paragon-icons

If that makes sense could you try that in your fork and confirm the checks attach to the PR?

Thanks for the thorough review, @bmtcril!

I pushed all the changes you advised. I did test the workflow_dispatch approach, and the extra step does trigger ci.yml as you proposed, but the PR itself still showed the "Workflows awaiting approval" banner, so I had to approve them by hand before the PR's own checks would run. That's expected behavior for PRs created with the default GITHUB_TOKEN:

https://docs.github.com/en/actions/concepts/security/github_token#when-github_token-triggers-workflow-runs

Since a PAT isn't desirable here, I tried a GitHub App instead and it worked cleanly on my fork, no approval step needed:

CI on that PR started on its own. It does show a red X, but only on the coverage step, since my fork has no CODECOV_TOKEN and the step uses fail_ci_if_error: true. All four tox environments pass.

The App is also GitHub's recommended approach for this kind of automation:

https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/deciding-when-to-build-a-github-app#choosing-between-a-github-app-or-a-personal-access-token

To be clear on what's where: this PR still has the workflow_dispatch version you advised. The App changes are only on my fork, in this commit:
carlos-marquez-wgu@daacc72

Unlike a PAT, the App is owned by the org, so an admin would need to create it in the openedx org and install it on this repo, then add APP_CLIENT_ID as a repo variable and APP_PRIVATE_KEY as a secret.

Let me know which approach you'd prefer. If it's the App, I'm glad to push the changes, and I'd appreciate a pointer on who could help with the org-side install.

cc @BryanttV, @rodmgwgu

@BryanttV

Copy link
Copy Markdown
Contributor

@carlos-marquez-wgu, I'm not sure how related this is to the PR, but ADR 0029 mentions that the make paragon_icons_check command should be integrated into CI to validate that the Paragon icons aren't out of date. Was this considered? Maybe we should have a separate PR to include it? cc @rodmgwgu

@arbrandes arbrandes left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a drive-by review of the architecture exposed here from a frontend perspective.

First: I'm surprised the Authz backend is concerning itself with presentation. The fact that it cares about icon names at all gives rise to complications such as the one this PR is trying to solve. It would've been best if this weren't needed at all.

Second, and this is the reason I wouldn't merge this: the assumption that admin-console decides what version of Paragon gets loaded in a site is at least partly incorrect: in frontend-base land (i.e., in frontend-app-admin-console@master), Paragon is a peer dependency. It's the downstream site that ends up actually picking.

Emphasis on downstream. The link above is to a template: each operator gets to pick what their site actually pulls in within the constraints of each app's package.json.

Assuming revisiting the decision to use Paragon icon names, or even the decision to couple this repo with presentation, is not feasible, here's what I would do instead:

Use the source of truth for what version of Paragon an upcoming release will support: the "dependency freeze" as announced by the Frontend Working Group (as governed by this ADR). Then modify the workflow to check for the latest released version of that major (currently 23), instead of pointing to any single frontend app.

Will this have to be manually updated down the line? Yes. But IMHO, it would be better than a brittle, ad hoc coupling.

@rodmgwgu

Copy link
Copy Markdown
Contributor

This is a drive-by review of the architecture exposed here from a frontend perspective.

First: I'm surprised the Authz backend is concerning itself with presentation. The fact that it cares about icon names at all gives rise to complications such as the one this PR is trying to solve. It would've been best if this weren't needed at all.

Second, and this is the reason I wouldn't merge this: the assumption that admin-console decides what version of Paragon gets loaded in a site is at least partly incorrect: in frontend-base land (i.e., in frontend-app-admin-console@master), Paragon is a peer dependency. It's the downstream site that ends up actually picking.

Emphasis on downstream. The link above is to a template: each operator gets to pick what their site actually pulls in within the constraints of each app's package.json.

Assuming revisiting the decision to use Paragon icon names, or even the decision to couple this repo with presentation, is not feasible, here's what I would do instead:

Use the source of truth for what version of Paragon an upcoming release will support: the "dependency freeze" as announced by the Frontend Working Group (as governed by this ADR). Then modify the workflow to check for the latest released version of that major (currently 23), instead of pointing to any single frontend app.

Will this have to be manually updated down the line? Yes. But IMHO, it would be better than a brittle, ad hoc coupling.

Thanks for reviewing this @arbrandes, some context and thoughts on this:

The reason openedx-authz is defining the icons here is because we are making roles and permissions extensible, so site operators or other modules can define new ones via the extensibility feature.

When displaying these in the UI, we show icons next to the permissions and permission categories, and thus we need a way to allow specifying these in the extension files.

Now, I do see the concern you are raising. I'm thinking on an alternative: Instead of defining paragon icons directly, we could define a subset of these that can be used for this feature (not necessarily using the same names Paragon gives them), and clearly document this.

That way we define an interface between openedx-authz and the admin-console independent from paragon, and then the admin-console would be in charge on keeping these icons available with whichever equivalent paragon or otherwise icon is available.

What do you think?

@carlos-marquez-wgu @BryanttV @mariajgrimaldi @dcoa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mao-onboarding Reviewing this will help onboard devs from an Axim mission-aligned organization (MAO). open-source-contribution PR author is not from Axim or 2U

Projects

Status: In Eng Review

Development

Successfully merging this pull request may close these issues.

Scheduled job to update Paragon icons list for validation

7 participants