{"id":20037794,"url":"https://github.com/openedx/openedx-webhooks","last_synced_at":"2025-05-05T06:31:28.333Z","repository":{"id":18466523,"uuid":"21661283","full_name":"openedx/openedx-webhooks","owner":"openedx","description":"Webhooks for the Open edX GitHub and JIRA","archived":false,"fork":false,"pushed_at":"2024-09-16T19:11:50.000Z","size":1438,"stargazers_count":11,"open_issues_count":16,"forks_count":20,"subscribers_count":61,"default_branch":"master","last_synced_at":"2024-09-17T00:19:20.442Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://openedx-webhooks.herokuapp.com/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openedx.png","metadata":{"files":{"readme":"README.rst","changelog":"changelog.d/README.txt","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-07-09T17:08:56.000Z","updated_at":"2024-09-11T15:12:21.000Z","dependencies_parsed_at":"2024-03-15T14:40:34.226Z","dependency_job_id":"bd314117-c463-4432-8659-9d6e7b4661fe","html_url":"https://github.com/openedx/openedx-webhooks","commit_stats":null,"previous_names":[],"tags_count":91,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openedx%2Fopenedx-webhooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openedx%2Fopenedx-webhooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openedx%2Fopenedx-webhooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openedx%2Fopenedx-webhooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openedx","download_url":"https://codeload.github.com/openedx/openedx-webhooks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224428798,"owners_count":17309586,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T10:22:18.048Z","updated_at":"2025-05-05T06:31:28.323Z","avatar_url":"https://github.com/openedx.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":".. highlight: sh\n\nOpen edX Webhooks Handlers (and Other JIRA/GitHub Utilities)\n============================================================\n\nWebhooks for `Open edX`_ integrating JIRA and GitHub. Designed to\nbe deployed at `Heroku`_.\n\n`Access the app`_ at https://openedx-webhooks.herokuapp.com.\n\n|Build Status| |Coverage Status| |Documentation badge|\n\nSet Up Development Environment\n------------------------------\n\nPrerequisites\n~~~~~~~~~~~~~\n\nMake sure you've installed:\n\n-  Python 3.12.x development environment\n   (virtualenv strongly recommended)\n-  `Heroku Command Line`_\n\n   All ``heroku`` commands can be performed through the Heroku web-based\n   dashboard as well, if you don't want to use the CLI.\n\nSet up\n~~~~~~\n\nLog in using the email address and password you used when creating\nyour Heroku account::\n\n    make deploy-configure\n\nAuthenticating is required to allow both the ``heroku`` and ``git``\ncommands to operate.\n\nAlternatively, to authenticate with SSH keys::\n\n    make deploy-configure DEPLOY_USE_SSH=true\n\nYou should see output similar to::\n\n    heroku  https://git.heroku.com/openedx-webhooks-staging.git (push)\n    heroku  https://git.heroku.com/openedx-webhooks-staging.git (fetch)\n    origin  git@github.com:edx/openedx-webhooks.git (fetch)\n    origin  git@github.com:edx/openedx-webhooks.git (push)\n\nDevelop\n-------\n\nThis app relies on the following addons from Heroku:\n\n-  Redis\n-  Papertrail\n-  Scheduler\n\nWhile it's possible to replicate the entire stack locally, it'll be\ndifficult to ensure consistent experience for each developer. Instead,\nwe utilize the `pipeline`_ facility offered by Heroku to handle our\ndevelopment needs.\n\nThe general development cycle is:\n\nCode → Deploy branch to staging → Test → Iterate\n\nTo deploy your current working branch to staging::\n\n    make deploy-stage-branch\n\nTo deploy an arbitrary branch::\n\n    make deploy-stage-branch DEPLOY_STAGING_BRANCH=feat/my-branch\n\nOnce you're satisfied with your changes, go ahead and open a pull\nrequest per normal development procedures.\n\nSmoke test the deployment.\n\nIf the application isn't running, visit the `openedx-webhooks-staging\nResources`_ page to make sure there are dynos running.\n\n.. _openedx-webhooks-staging Resources: https://dashboard.heroku.com/apps/openedx-webhooks-staging/resources\n\n\nRun Tests\n---------\n\n::\n\n    make install-dev-requirements test\n\nIf you are testing a change to `repo-tools-data-schema`_, you need to coordinate\nchanges in both repos:\n\n- Name your branch here the same as your branch in repo-tools-data-schema.\n\n- Be sure your changes in repo-tools-data-schema are pushed to your branch on\n  GitHub.\n\n- Run ``make testschema`` to install your branch of repo-tools-data-schema in\n  this virtualenv.\n\n- Run tests here as usual.\n\n.. _repo-tools-data-schema: https://github.com/openedx/repo-tools-data-schema\n\nDeploy\n------\n\nIn most cases, you'll want to deploy by promoting from staging to\nproduction. The general workflow is:\n\nMerge to ``master`` → Deploy ``master`` to staging → Test → Promote to\nproduction\n\n**Prior to the promotion**, make sure all the changes have been merged\nto ``master``, and you've deployed the ``master`` branch successfully to\nstaging::\n\n    make deploy-stage\n\nWhen you're ready to promote from staging to production::\n\n    make deploy-prod\n\nMake sure the same git commit is deployed to both environments.\n\nMake sure the abbreviated git SHAs match.\n\nSmoke test the deployment.\n\n\nOther things to know\n--------------------\n\n**This should no longer be an issue as of July 9th, 2018.**\n\nIf you re-process pull requests, an unfortunate thing can happen: it will find\nstale pull requests that were written by edX employees who have now left.  The\nbot will see that the author has no contributor agreement, and will make a new\nJIRA issue for the pull request.  This is needless noise.\n\nThe bot looks for comments it wrote that have a JIRA issue id in them.  You can\nleave the bot comment on the stale pull request so that at least it won't happen\nagain in the future.\n\n\nConfiguring a webhook\n---------------------\n\nOn GitHub, visit the repo webhooks\n(``https://github.com/\u003cORG\u003e/\u003cREPO\u003e/settings/hooks``) or organization webhooks\n(``https://github.com/organizations/\u003cORG\u003e/settings/hooks``) page.\n\nCreate or edit a webhook.\n\n- Payload URL: https://openedx-webhooks.herokuapp.com/github/hook-receiver\n- Content type: application/json\n- Secret: same as setting GITHUB_WEBHOOK_SECRET in Heroku\n- Events:\n    - Issue comments\n    - Pull requests\n    - Pull request reviews\n    - Pull request review comments\n\n\n\nChangelog\n---------\n\nUnreleased\n~~~~~~~~~~\n\nSee the fragment files (if any) in the changelog.d directory.\n\n.. scriv-insert-here\n\n2025-02-24\n~~~~~~~~~~\n\n- Add support for Python 3.12\n\n2023-12-07\n~~~~~~~~~~\n\n- When a pull request is closed, if it doesn't have a\n  \"open-source-contribution\" label on it, it is considered an internal pull\n  request.  We assume that it was processed when it was opened, and since it\n  didn't get the label then, the author must have been internal at the time.\n\n2023-11-27\n~~~~~~~~~~\n\n- Now issues created in Jira will have a label of \"from-GitHub\" on them. Closes\n  `issue 279`_.\n\n- Two possible errors with \"jira:foo\" labels now create bot comments so people\n  understand why there's no Jira issue. Closes `issue 280`_.\n\n- Fix: we no longer comment twice on a pull request closed with a comment.\n  Closes `issue 277`_.\n\n.. _issue 277: https://github.com/openedx/openedx-webhooks/issues/277\n.. _issue 279: https://github.com/openedx/openedx-webhooks/issues/279\n.. _issue 280: https://github.com/openedx/openedx-webhooks/issues/280\n\n\n2023-11-03\n~~~~~~~~~~\n\n- Don't add a \"no contributions accepted\" comment if the pull request is being\n  closed. It's needlessly discouraging. Fixed #273.\n\n2023-10-31\n~~~~~~~~~~\n\n- Adding a label like ``jira:xyz`` to a pull request will look in a private\n  registry of Jira servers for one nicknamed ``xyz``, and then create a Jira\n  issue there to correspond to the pull request.\n\n2023-09-13\n~~~~~~~~~~\n\n- The CLA check used to fail if a pull request had more than 100 commits.  Now\n  the head sha is retrieved directly without listing all commits, so the number\n  is irrelevant.\n\n2023-08-30\n~~~~~~~~~~\n\n- Adding a comment to pull request now re-runs the checks and updates the state\n  of the pull request.  Previously, we'd edit the title of the PR to trigger\n  updates.\n\n2023-08-11\n~~~~~~~~~~\n\n- Removed: the bot no longer understands the past state of users.  This data\n  hasn't been maintained for the last few years.  There's no point relying on\n  stale data, so the capability is removed.\n\n- Removed: any understanding of who is a core contributor.  The bot no longer\n  makes comments or labels particular to core contributors. `Issue 227`_.\n\n.. _issue 227: https://github.com/openedx/openedx-webhooks/issues/227\n\n- Removed: we no longer read people.yaml.\n\n- Removed: we no longer add \"jenkins ok to test\" to start testing, since that\n  comment was only read by Jenkins, which we no longer use.\n\n2023-08-03\n~~~~~~~~~~\n\n- Jira authentication now uses the JIRA_USER_EMAIL and JIRA_USER_TOKEN\n  environment variables.  OAuth authentication is removed. These settings are\n  now obsolete and can be deleted:\n\n  - DATABASE_URL\n  - GITHUB_OAUTH_CLIENT_ID\n  - GITHUB_OAUTH_CLIENT_SECRET\n  - JIRA_OAUTH_CONSUMER_KEY\n  - JIRA_OAUTH_RSA_KEY\n  - SQLALCHEMY_DATABASE_URI\n\n- Stopped the bot from updating a repository's labels based on ``labels.yaml``, as this is now handled by the `repo_checks \u003chttps://github.com/openedx/repo-tools/tree/master/edx_repo_tools/repo_checks\u003e`_ tool. The ``labels.yaml`` file is now unused and can be safely deleted from any openedx-webhooks data repositories.\n\n- Stopped the bot from adding the ``core committer`` GitHub label to pull requests to repos on which the bot believes the author to have write access. The bot's data source for repository access, ``people.yaml``, is outdated, we do not yet have a strategy for keeping it updated. Until further notice, coding Core Contributors are asked to add the ``core contributor`` label to their pull requests manually.\n\n2023-03-03\n~~~~~~~~~~\n\n- Removed the code that used the now-obsolete ``internal`` setting in\n  orgs.yaml.\n\n- Tweaked the CLA messages.\n\n2023-03-02\n~~~~~~~~~~\n\n- The \"internal\" setting is being replaced by an \"internal-ghorgs\" list on an\n  institution.  A pull request is now internal if the author's associated\n  institution (in orgs.yaml) has the org the PR is being made to as an\n  internal-ghorgs org.  The old \"internal\" setting is still used, but we'll be\n  deleting it once the new code is in place.\n\n2023-01-30\n~~~~~~~~~~\n\n- Added: contribution pull requests will be added to GitHub projects if the\n  base repo says to by adding an \"openedx.org/add-to-projects\" annotation in\n  its catalog-info.yaml file.\n\n2022-07-21\n~~~~~~~~~~\n\n- Adding a pull request to a project could fail if the two are in different\n  GitHub orgs (like edx and openedx).  This failure used to stop the bot from\n  making further changes, but now we log the exception and continue.\n\n2022-06-13\n~~~~~~~~~~\n\n- Removing the JIRA_SERVER setting will disable Jira access for the bot. No Jira\n  issues will be created or updated.\n\n2022-06-03\n~~~~~~~~~~\n\n- Blended pull requests now go into a separate project, specified with\n  the GITHUB_BLENDED_PROJECT setting.\n\n2022-06-01\n~~~~~~~~~~\n\n- The JIRA server is now configurable with the JIRA_SERVER environment\n  variable.\n\n- New external pull requests will be added to a GitHub project.  The project is\n  configurable with the GITHUB_OSPR_PROJECT environment variable.\n\n- Removed mention of unused JIRA credentials JIRA_ACCESS_TOKEN and\n  JIRA_ACCESS_TOKEN_SECRET.\n\n2022-04-06\n~~~~~~~~~~\n\n- Repos with more than 30 labels might not have properly labelled pull requests\n  that transitioned into late-alphabet statuses (like Open edX Community\n  Review).  This is now fixed.\n\n2022-04-05\n~~~~~~~~~~\n\n- Load yaml and csv data files from the `openedx/openedx-webhooks-data` repo.\n\n2022-03-25\n~~~~~~~~~~\n\n- Pull requests can now be closed and re-opened.  When the pull request is\n  re-opened, the survey comment that was added on closing is deleted.  The Jira\n  ticket is returned to the state it was in before the pull request was closed.\n\n2022-01-27\n~~~~~~~~~~\n\n- Removed the code that handled \"contractor\" pull requests, where the bot\n  couldn't know if an OSPR ticket was needed or not.\n\n- The CLA check is now applied to all pull requests, even edX internal ones.\n\n2021-12-20\n~~~~~~~~~~\n\n- The bot now ignores any private repo in the edx organization.\n\n2021-12-17\n~~~~~~~~~~\n\n- We no longer use OAuth authentication for GitHub.  All access is with a\n  personal access token.\n\n- The bot now depends on a csv generated by Salesforce to inform which users\n  have signed the Contributor License Agreement (CLA)\n\n- After processing a pull request, the GitHub rate limit is checked and logged:\n    Rate limit: 5000, used 29, remaining 4971. Reset is at 2021-12-16 23:26:48\n\n- The \"needs CLA\" message now includes the possibility that you've signed\n  before and need to re-sign.\n\n2021-09-29\n~~~~~~~~~~\n\n- Removed the NEED-CLA label. We have a check now, which is better.\n\n2021-09-14\n~~~~~~~~~~\n\n- Due to an internal refactoring, now rescanning pull requests will add the\n  end-of-pull-request survey comment if needed.\n\n- Four Jira fields are no longer updated:\n    'Github PR Last Updated At'\n    'Github PR Last Updated By'\n    'Github Latest Action'\n    'Github Latest Action by edX'\n\n2021-09-13\n~~~~~~~~~~\n\n- A GitHub check indicates whether the author has a contributor agreement or\n  not.\n\n2021-09-02\n~~~~~~~~~~\n\n- Fix an assertion error that could happen if a pull request had no body\n  (description).  The assertion was:\n\n      File \"/app/openedx_webhooks/tasks/jira_work.py\", line 117, in update_jira_issue\n        assert fields\n\n- Change error handling so that more actions can complete even if one fails.\n\n2021-08-30\n~~~~~~~~~~\n\n- Removed one setting: JIRA_OAUTH_PRIVATE_KEY, which was just JIRA_OAUTH_RSA_KEY base64 encoded.\n\n2021-08-18\n~~~~~~~~~~\n\n- fix: all UI pages are now protected with basic auth.\n\n2021-02-25\n~~~~~~~~~~\n\n- Update the CLA link to go to https://openedx.org/cla, which currently\n  redirects to our new Docusign form.  If we have to change the form in the\n  future, we can change the redirect on openedx.org.\n\n2021-01-22\n~~~~~~~~~~\n\n- When considering a pull request, we won't update the Jira extra fields if\n  none of our desired fields are different.  We used to update a Jira issue if\n  (for example) it had platform map info, but we didn't want to add platform\n  map info.\n\n2021-01-21\n~~~~~~~~~~\n\n- More control over rescanning:\n\n  - You can provide an earliest and latest date to consider.  Only pull\n    requests created within that window will be rescanned.\n\n    Rescanning never considers pull requests created before 2018.  This is a\n    quick fix to deal with contractor comments.\n\n    Because we don't track when companies started and stopped being\n    contractors, we can't decide now if a pull request should have had a\n    contractor comment when it was created.\n\n    The latest contractor comment on one of our pull requests was in December\n    2017.  So don't consider pull requests that old.  Later we can implement a\n    better solution if we need to rescan those old pull requests.\n\n  - Rescanning now has a dry-run mode which records what would have been done,\n    but takes no action.\n\n- Before-clauses in people.yaml are now handled differently.  Previously, only\n  one before clause was found, the earliest one that applied to the date we're\n  interested in.  Now, all before clauses that apply (with dates after the date\n  we are interested in) are layered together starting with now and working\n  back in time to build a dict of data.\n\n- Updates to Jira tickets will try not to notify users unless the title or body\n  (summary or description) change.  This requires that the bot Jira user be an\n  administrator of the projects it is updating.\n\n2021-01-08\n~~~~~~~~~~\n\n- Rescanning changes:\n\n  - Now you have the option to include closed pull requests.\n\n  - Pull requests are fetched in full to ensure all the needed fields will be\n    available.\n\n2020-11-24\n~~~~~~~~~~\n\n- The bot used to create a Jira issue to replace an issue that had been\n  deleted.  This interfered with rescanning, so the bot no longer does this.\n  If a Jira issue mentioned in the bot comment has been deleted, it will not be\n  recreated.\n\n2020-10-29\n~~~~~~~~~~\n\n- The number of lines added and deleted by a pull request are recorded in\n  custom Jira fields.\n\n2020-10-15\n~~~~~~~~~~\n\n- Core Committer pull requests now start with a Jira status of \"Waiting on\n  Author\" rather than \"Open edX Community Review\".\n\n2020-09-23\n~~~~~~~~~~\n\n- Draft pull requests start with a status of \"Waiting on Author\".  Once the\n  pull request is no longer a draft, the status is set to the initial status it\n  would have originally had.\n\n2020-08-08\n~~~~~~~~~~\n\n- BUG: if the PR description was edited, the Jira issue status would be\n  incorrectly reset to its initial value [OPENEDX-424].  This is now fixed.\n\n2020-08-07\n~~~~~~~~~~\n\n- When a core committer merges a pull request, the bot will add a comment\n  pinging the committer's edX champions to let them know the merge has\n  happened.\n\n- BUG: previously the bot could clobber ad-hoc labels on Jira issues when it\n  set its own labels.  This is now fixed.  The bot will preserve any labels it\n  didn't make.\n\n- Removed the code that managed webhooks in repos.\n\n- Refactored some code that handles pull requests being closed, so now it\n  operates on any change to the pull request.  The behavior should be the same,\n  except now if a pull request is closed or merged after the Jira issue has\n  been manually deleted, the bot will create a new issue so that it can mark it\n  Rejected or Merged.\n\n\n2020-07-24\n~~~~~~~~~~\n\n- BUG: previously, the bot might change GitHub labels and incorrectly drop\n  ad-hoc labels that people had put on the pull request.  This is now fixed.\n\n\n2020-07-23\n~~~~~~~~~~\n\n- GitHub very occasionally sends us a pull request event, but then serves us a\n  404 error when we ask it about the pull request.  Now the bot will retry GET\n  requests that return 404, to give GitHub a chance to get its act together.\n\n- BUG: when a pull request was edited, the associated Jira issue would be reset\n  to its initial status.  This is now fixed: the Jira status is unchanged.\n\n\n2020-07-21\n~~~~~~~~~~\n\n- Previously, if an OSPR issue had been manually moved to BLENDED, and then the\n  title of the pull request amended to have \"[BD-xx]\", the bot would try and\n  fail to delete the moved issue.  Now it understands the move, and doesn't\n  try to delete the original issue.  It also updates the issue with Blended\n  information.\n\n\n2020-07-20\n~~~~~~~~~~\n\n- Changes to the title or description of a pull request are copied over to the\n  associated Jira issue to keep them in sync.\n\n- If a change to a pull request requires a different Jira issue, the old issue\n  is deleted, and a new one made.  For example, if a blended pull request\n  doesn't have \"[BD-xx]\" in the title, an OSPR issue gets made initially.\n  Now when the developer updates the title, the OSPR issue is deleted, and a\n  new BLENDED issue is created for it.\n\n\n2020-07-14\n~~~~~~~~~~\n\n- The \"expires_on\" key in people.yaml is officially obsolete, and no longer\n  interpreted.\n\n- Some incorrect CLA logic was fixed. An entry in people.yaml with no\n  \"expires_on\" key would be considered to have a signed CLA, even if the\n  agreement was \"none\".\n\n\n2020-07-02\n~~~~~~~~~~\n\n- If an opened pull request has a CLA, then the bot will comment \"jenkins ok to\n  test\" on it to get the tests started automatically.\n\n\n2020-07-01\n~~~~~~~~~~\n\n- Blended workflow: if \"[BD-XX]\" is found in the title of an opened pull\n  request, then the Jira ticket will be in the BLENDED project, with links to\n  the correct epic, etc.\n\n\n2020-06-25\n~~~~~~~~~~\n\n- Core committer logic has to be particular to specific repos, it's not a\n  blanket right.  Now \"committer\" isn't a simple boolean, it's an object with\n  subkeys: \"repos\" is a list of repos the user can commit to, and \"orgs\" is a\n  list of GitHub organizations the user can commit to (any repo).\n\n\n2020-06-24\n~~~~~~~~~~\n\n- Slight change to people.yaml schema: \"internal:true\" is used to indicate edX\n  people (or Arbisoft).  The \"committer:true\" flag indicates core committers.\n\n- Core committer pull request handling: a different welcome message is used,\n  OSPR issues are started in the \"Open edX Community Review\" status, and \"core\n  committer\" GitHub and Jira labels are applied.\n\n\n2020-06-19\n~~~~~~~~~~\n\n- We used to have two GitHub webhooks.  They have been combined.  Only\n  /github/hook-receiver is needed now.  The obsolete /github/pr endpoint still\n  exists just to log unneeded webhook action so we can fix the GitHub\n  configuration.\n\n\n2020-06-15\n~~~~~~~~~~\n\n- Labels in GitHub repos are synchronized from repo-tools-data/labels.yaml\n  before any labels are adjusted in the repo.\n\n- Data read from repo-tools-data (people.yaml, label.yaml) is only cached for\n  15 minutes. It used to be until the bot was restarted.\n\n\n2020-06-08\n~~~~~~~~~~\n\n- Pull requests that need a CLA signed now create Jira tickets in the\n  \"Community Manager Review\" status.\n\n\nTODO\n----\n\n-  Describe the different processes that are run on Heroku\n-  Describe how to access logs\n-  Make sure ``docs/`` is up to date\n\n.. _Open edX: http://openedx.org\n.. _Heroku: http://heroku.com\n.. _Access the app: https://openedx-webhooks.herokuapp.com\n.. _Heroku Command Line: https://devcenter.heroku.com/articles/heroku-command-line\n.. _pipeline: https://devcenter.heroku.com/articles/pipelines\n\n.. |build-status| image:: https://github.com/openedx/openedx-webhooks/workflows/Python%20CI/badge.svg?branch=master\n   :target: https://github.com/openedx/openedx-webhooks/actions?query=workflow%3A%22Python+CI%22\n.. |Coverage Status| image:: http://codecov.io/github/edx/openedx-webhooks/coverage.svg?branch=master\n   :target: http://codecov.io/github/edx/openedx-webhooks?branch=master\n.. |Documentation badge| image:: https://readthedocs.org/projects/openedx-webhooks/badge/?version=latest\n   :target: http://openedx-webhooks.readthedocs.org/en/latest/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenedx%2Fopenedx-webhooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenedx%2Fopenedx-webhooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenedx%2Fopenedx-webhooks/lists"}