{"id":20077650,"url":"https://github.com/stolostron/magic-mirror","last_synced_at":"2025-07-10T19:06:56.633Z","repository":{"id":37582301,"uuid":"498487701","full_name":"stolostron/magic-mirror","owner":"stolostron","description":"A GitHub app that mirrors (cherry picks) from upstream to downstream using PRs.","archived":false,"fork":false,"pushed_at":"2025-04-29T14:26:53.000Z","size":1363,"stargazers_count":0,"open_issues_count":4,"forks_count":2,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-29T15:38:48.042Z","etag":null,"topics":["app","cherry-pick","fork","github","upstream"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stolostron.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG/CHANGELOG-v1.1.0.md","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,"zenodo":null}},"created_at":"2022-05-31T20:27:43.000Z","updated_at":"2025-04-29T14:22:59.000Z","dependencies_parsed_at":"2024-03-18T14:31:21.598Z","dependency_job_id":"c0fb5a46-5a40-4696-814b-83526ff9d41d","html_url":"https://github.com/stolostron/magic-mirror","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stolostron%2Fmagic-mirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stolostron%2Fmagic-mirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stolostron%2Fmagic-mirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stolostron%2Fmagic-mirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stolostron","download_url":"https://codeload.github.com/stolostron/magic-mirror/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252586068,"owners_count":21772247,"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":["app","cherry-pick","fork","github","upstream"],"created_at":"2024-11-13T15:09:35.928Z","updated_at":"2025-05-05T22:31:13.987Z","avatar_url":"https://github.com/stolostron.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Magic Mirror\n\nMagic Mirror is a [GitHub App](https://docs.github.com/en/developers/apps/getting-started-with-apps/about-apps) that\nmirrors (cherry picks) merged upstream pull-requests (PR) to configured forked repository's branches. It does this by\ncreating cherry pick PRs on the forked repository and automatically merging them if the PR CI passes. This also has the\nadded benefit of documenting each upstream PR that is synced.\n\nIf a sync from upstream fails, a GitHub issue is created on the forked repository. In that event, Magic Mirror will\npause syncing the forked repository's branch that failure occurred on until the GitHub issue is closed. Therefore,\nclosing the GitHub issue signals to Magic Mirror that the failed sync was manually corrected or can be ignored.\n\n## GitHub Installation\n\nInstalling Magic Mirror on a particular GitHub repository indicates that it should be synced with upstream. Additional\nconfiguration as described in the [Configuration](#configuration) section is still required.\n\n## GitHub Repository Configuration\n\n### Upstream Repositories\n\nThe upstream repository must use the \"rebase\" merge method on all pull-requests (PRs) or require that all PRs only\ncontain a single commit. The reason is that Magic Mirror is unable to detect which merge method was used on the upstream\nPR.\n\n### Forked Repositories\n\nForked repositories must have the following configured:\n\n- [Required status checks before merging](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#require-status-checks-before-merging)\n  if you'd like for CI to pass before the cherry-pick PR is merged.\n- [Rebase merges](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/about-merge-methods-on-github#rebasing-and-merging-your-commits)\n  are enabled.\n- Merges must not require an\n  [approval](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/about-protected-branches#require-pull-request-reviews-before-merging).\n- It's also recommended to enable\n  [automatic deletion of branches](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-the-automatic-deletion-of-branches)\n  since Magic Mirror works by creating temporary branches on the forked repository.\n\n### Permissions\n\nThe GitHub App requires the following repository permissions:\n\n- [Checks](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps#permission-on-checks) read\n  access. This is needed to verify that the CI on a PR has passed.\n- [Commit statuses](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps#permission-on-statuses)\n  read access. This is needed to verify that the CI on a PR has passed.\n- [Contents](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps#permission-on-contents) read\n  and write access. This is needed so that repository can be cloned and a branch created with the cherry picked upstream\n  commits.\n- [Issues](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps#permission-on-issues) read and\n  write access. This is needed so that the a GitHub issue can be created if a sync from upstream fails.\n- [Metadata](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps#metadata-permissions) read\n  access. This is mandatory for all GitHub apps.\n- [Pull requests](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps#permission-on-pull-requests)\n  read and write access. This is needed so that PRs can be created and closed.\n\n### Events\n\nThe GitHub app requires being subscribed to the following events:\n\n- [Check run](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#check_suite)\n- [Issues](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#issues)\n- [Pull request](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#pull_request)\n- [Status](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#status)\n\n## Configuration\n\nThe configuration file must be present at `./config.json` or `/etc/magic-mirror/config.json`.\n\n- `appID` - the GitHub App ID that is used during authentication with the GitHub API.\n- `dbPath` - an optional path to the SQLite database to use or create. This defaults to\n  `/etc/magic-mirror/magic-mirror.db`.\n- `logLevel` - an optional log level to set. This defaults to `info`. Other options include `debug` or `error`.\n- `privateKeyPath` - an optional path to the GitHub App private key used during authentication with the GitHub API. This\n  defaults to `/etc/magic-mirror/auth.key`.\n- `syncInterval` - an optional interval in seconds for how often Magic Mirror should check for new merged upstream PRs.\n  This defaults to `30`.\n- `upstreamMappings` - the object that determines which upstream branches should be synced to which fork branches. See\n  the example configure below for a better understanding.\n- `webhookSecret` - the optional secret that the GitHub webhook event must provide for it to be processed.\n\nBelow is an example configuration that syncs from the `main` and `release-0.7` branches in the\n`open-cluster-management-io` GitHub organization to the `release-2.6` and `release-2.5` branches in the `stolostron`\nGitHub organization respectively. Note that the repositories that are synced would be determined based on which\n`stolostron` repositories by the same name as in `open-cluster-management-io` are selected in the GitHub App\ninstallation.\n\n```json\n{\n  \"appID\": 2,\n  \"dbPath\": \"/etc/magic-mirror/magic-mirror.db\",\n  \"logLevel\": \"info\",\n  \"privateKeyPath\": \"/etc/magic-mirror/auth.key\",\n  \"syncInterval\": 30,\n  \"upstreamMappings\": {\n    \"stolostron\": {\n      \"open-cluster-management-io\": {\n        \"branchMappings\": {\n          \"main\": \"release-2.6\",\n          \"release-0.7\": \"release-2.5\"\n        }\n      }\n    }\n  },\n  \"webhookSecret\": \"my-secret\"\n}\n```\n\n## Deployment\n\n### Architecture\n\n\u003cimg src=\"images/architecture.png\" alt=\"architecture diagram\" width=\"400px\" /\u003e\n\n### Prerequisites\n\n- [Create](https://docs.github.com/en/developers/apps/building-github-apps/creating-a-github-app) a GitHub App in the\n  GitHub organization with the forks.\n  - Set the webhook URL to the root of where you plan to deploy Magic Mirror.\n  - Set the documented [permissions](#permissions) and webhook [events](#events).\n  - Set a webhook secret.\n- Create a `config.json` file based on the [documentation](#configuration).\n- [Download](https://docs.github.com/en/developers/apps/building-github-apps/authenticating-with-github-apps#generating-a-private-key)\n  a generated private key of your GitHub App and name it `auth.key`.\n\n### Kubernetes\n\nAfter completing the [prerequisites](#prerequisites), start by creating a namespace to deploy Magic Mirror in.\n\n```shell\nkubectl create namespace magic-mirror\n```\n\nCreate the Kubernetes secret to contain the `config.json` and `auth.key` files setup during the\n[prerequisite](#prerequisites) steps.\n\n```shell\nkubectl create -n magic-mirror secret generic magic-mirror-config --from-file=config.json --from-file=auth.key\n```\n\nThen fill out a `values.yaml` file to customize the [Helm chart's](helm/) default [values.yaml](helm/values.yaml) file.\nBelow is an example that utilizes [OpenShift's](https://www.redhat.com/en/technologies/cloud-computing/openshift)\ndefault certificate for TLS termination.\n\n```yaml\ningress:\n  # Change this to the actual external DNS name that GitHub will use to send webhook events.\n  host: magic-mirror.apps.openshift.example.com\n  annotations:\n    route.openshift.io/termination: edge\n\nconfigSecret: magic-mirror-config\n```\n\nOnce you are happy with your `values.yaml` file, you may install Magic Mirror using the following Helm command from the\nroot of the Git repository.\n\n```shell\nhelm install magic-mirror ./helm -f values.yaml --namespace=magic-mirror\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstolostron%2Fmagic-mirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstolostron%2Fmagic-mirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstolostron%2Fmagic-mirror/lists"}