Skip to content

Commit 692c18b

Browse files
committed
🎉 Initial commit
0 parents  commit 692c18b

15 files changed

+9157
-0
lines changed

.env.example

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# The ID of your GitHub App
2+
APP_ID=
3+
WEBHOOK_SECRET=development
4+
5+
# Use `trace` to get verbose logging or `info` to show less
6+
LOG_LEVEL=debug
7+
8+
# Go to https://smee.io/new set this to the URL that you are redirected to.
9+
WEBHOOK_PROXY_URL=

.github/CODE_OF_CONDUCT.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Contributor Covenant Code of Conduct
2+
3+
## Our Pledge
4+
5+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
6+
7+
## Our Standards
8+
9+
Examples of behavior that contributes to creating a positive environment include:
10+
11+
* Using welcoming and inclusive language
12+
* Being respectful of differing viewpoints and experiences
13+
* Gracefully accepting constructive criticism
14+
* Focusing on what is best for the community
15+
* Showing empathy towards other community members
16+
17+
Examples of unacceptable behavior by participants include:
18+
19+
* The use of sexualized language or imagery and unwelcome sexual attention or advances
20+
* Trolling, insulting/derogatory comments, and personal or political attacks
21+
* Public or private harassment
22+
* Publishing others' private information, such as a physical or electronic address, without explicit permission
23+
* Other conduct which could reasonably be considered inappropriate in a professional setting
24+
25+
## Our Responsibilities
26+
27+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
28+
29+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
30+
31+
## Scope
32+
33+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
34+
35+
## Enforcement
36+
37+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [email protected]. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
38+
39+
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
40+
41+
## Attribution
42+
43+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
44+
45+
[homepage]: http://contributor-covenant.org
46+
[version]: http://contributor-covenant.org/version/1/4/

.github/CONTRIBUTING.md

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
## Contributing
2+
3+
[fork]: /fork
4+
[pr]: /compare
5+
[style]: https://standardjs.com/
6+
[code-of-conduct]: CODE_OF_CONDUCT.md
7+
8+
Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great.
9+
10+
Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms.
11+
12+
## Submitting a pull request
13+
14+
1. [Fork][fork] and clone the repository
15+
1. Configure and install the dependencies: `npm install`
16+
1. Make sure the tests pass on your machine: `npm test`, note: these tests also apply the linter, so no need to lint separately
17+
1. Create a new branch: `git checkout -b my-branch-name`
18+
1. Make your change, add tests, and make sure the tests still pass
19+
1. Push to your fork and [submit a pull request][pr]
20+
1. Pat your self on the back and wait for your pull request to be reviewed and merged.
21+
22+
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
23+
24+
- Follow the [style guide][style] which is using standard. Any linting errors should be shown when running `npm test`
25+
- Write and update tests.
26+
- Keep your change as focused as possible. If there are multiple changes you would like to make that are not dependent upon each other, consider submitting them as separate pull requests.
27+
- Write a [good commit message](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
28+
29+
Work in Progress pull request are also welcome to get feedback early on, or if there is something blocked you.
30+
31+
## Resources
32+
33+
- [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/)
34+
- [Using Pull Requests](https://help.github.com/articles/about-pull-requests/)
35+
- [GitHub Help](https://help.github.com)

.github/sync-up.yml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
version: "1"
2+
rules:
3+
master:
4+
upstream: wei:master
5+
autoMerge: true
6+
autoMergeHardReset: true

.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
coverage
3+
npm-debug.log
4+
*.pem
5+
.env

.travis.yml

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
language: node_js
2+
node_js:
3+
- node
4+
cache:
5+
directories:
6+
- node_modules
7+
install:
8+
- npm i
9+
script:
10+
- npm test
11+
branches:
12+
only:
13+
- master
14+
- /^feature-.*/
15+
after_success:
16+
- npm i codecov && codecov

README.md

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<img align="right" width="120" height="120" src="https://user-images.githubusercontent.com/5880908/40619990-2deb6502-6265-11e8-88c3-f2bcbac74a42.png" />
2+
3+
# Sync Up
4+
5+
[![TravisCI](https://travis-ci.com/wei/sync-up.svg?branch=master)](https://travis-ci.com/wei/sync-up)
6+
[![Codecov](https://codecov.io/gh/wei/sync-up/branch/master/graph/badge.svg)](https://codecov.io/gh/wei/sync-up)
7+
[![Depfu](https://img.shields.io/depfu/wei/sync-up.svg)](https://depfu.com/github/wei/sync-up)
8+
<br/>
9+
[![Probot](https://img.shields.io/badge/built%20with-probot-orange.svg)](https://probot.github.io/)
10+
[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
11+
[![jest](https://facebook.github.io/jest/img/jest-badge.svg)](https://github.com/facebook/jest)
12+
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://wei.mit-license.org)
13+
14+
> a GitHub App built with [probot](https://github.com/probot/probot) that keeps your repository up-to-date with upstream changes via automatic pull requests.
15+
16+
17+
## Features
18+
19+
1. A pull request is created when a specified upstream is updated (checking periodically).
20+
2. The pull request can be automatically merged.
21+
_Upstream must be in the same fork network_
22+
23+
## Setup
24+
25+
Recommended setup:
26+
1. Fork a repository
27+
2. Create a new branch
28+
3. Setup the new branch as Default branch under repository Settings > Branches
29+
4. Add `.github/sync-up.yml` to your default branch.
30+
31+
```yaml
32+
version: "1"
33+
rules: # Array of branches to sync
34+
master:
35+
upstream: wei:master # Required. Must be in the same fork network
36+
autoMerge: true # Optional, Default: false
37+
autoMergeHardReset: true # Optional, Default: false. Dangerous!! Remove merge commits along with any changes to the specified branch
38+
dev:
39+
upstream: master
40+
label: "sync-up :arrow_up_down:" # Optional
41+
assignees: # Optional
42+
- wei
43+
reviewers: # Optional
44+
- wei
45+
```
46+
47+
5. Install Sync Up app via https://github.com/apps/sync-up and select only the repos you wish to sync up.
48+
49+
## Author
50+
[Wei He](https://github.com/wei) [email protected]_
51+
52+
## License
53+
[MIT](https://wei.mit-license.org)

index.js

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
const SYNCUP_CONFIG = process.env.SYNCUP_CONFIG || 'sync-up.yml'
2+
3+
const getConfig = require('probot-config')
4+
const createScheduler = require('probot-scheduler')
5+
const fetch = require('node-fetch')
6+
const yaml = require('js-yaml')
7+
8+
const SyncUp = require('./lib/sync-up')
9+
const schema = require('./lib/schema')
10+
11+
module.exports = async (robot) => {
12+
const scheduler = createScheduler(robot)
13+
14+
robot.on('schedule.repository', routineCheck)
15+
robot.on('push', handlePush)
16+
robot.on(['pull_request', 'pull_request_review'], checkPRStatus)
17+
18+
async function handlePush (context) {
19+
if (context.payload.commits.filter(c => c.message.indexOf(SYNCUP_CONFIG) > -1).length > 0) {
20+
await routineCheck(context)
21+
}
22+
}
23+
24+
async function routineCheck (context) {
25+
const syncUp = await forRepository(context)
26+
if (syncUp) await syncUp.routineCheck()
27+
}
28+
29+
async function checkPRStatus (context) {
30+
switch (context.event) {
31+
case 'pull_request':
32+
if (context.payload.action !== 'opened') {
33+
return
34+
}
35+
break
36+
case 'pull_request_review':
37+
if (context.payload.action !== 'submitted' || context.payload.review.state !== 'approved') {
38+
return
39+
}
40+
break
41+
default:
42+
return
43+
}
44+
45+
const syncUp = await forRepository(context)
46+
if (syncUp) await syncUp.checkAutoMerge(context.payload.pull_request)
47+
}
48+
49+
async function forRepository (context) {
50+
if (!context.payload.repository.fork) {
51+
scheduler.stop(context.payload.repository)
52+
return null
53+
}
54+
55+
const config = await getConfig(context, SYNCUP_CONFIG)
56+
if (!config) {
57+
scheduler.stop(context.payload.repository)
58+
return null
59+
}
60+
61+
return new SyncUp(context.github, context.repo({ logger: robot.log }), config)
62+
}
63+
64+
const app = robot.route('/_')
65+
66+
app.get('/check/:owner/:repo', (req, res) => {
67+
fetch(`https://api.github.com/repos/${req.params.owner}/${req.params.repo}/contents/.github/${SYNCUP_CONFIG}`)
68+
.then(githubRes => githubRes.json())
69+
.then(json => Buffer.from(json.content, 'base64').toString())
70+
.then(yml => yaml.safeLoad(yml))
71+
.then((config) => {
72+
const { error, value } = schema.validate(config)
73+
if (error) throw error
74+
res.end(JSON.stringify(value, null, 2))
75+
})
76+
.catch((e) => {
77+
res.status(400).end(`File not found or invalid`)
78+
})
79+
})
80+
}

lib/helper.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
exports.timeout = ms => new Promise((resolve, reject) => setTimeout(resolve, ms))
2+
3+
exports.getPRTitle = (ref, upstream) =>
4+
`[sync-up] ${ref} from ${upstream}`
5+
6+
exports.getPRBody = (repoPath, prNumber) =>
7+
(prNumber
8+
? `See [Commits](/${repoPath}/pull/${prNumber}/commits) and [Diffs](/${repoPath}/pull/${prNumber}/files) for more details.\n\n-----\nCreated by [sync-up](https://github.com/wei/sync-up)`
9+
: 'Processing...')

lib/schema.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const Joi = require('joi')
2+
3+
const fields = {
4+
5+
version: Joi.string()
6+
.description('Version number (string)'),
7+
8+
branch: Joi.string()
9+
.description('Destination local branch'),
10+
11+
upstream: Joi.string()
12+
.description('Upstream owner:branch'),
13+
14+
autoMerge: Joi.boolean()
15+
.description('Set to true to auto merge pull requests (defaults to false)'),
16+
17+
autoMergeHardReset: Joi.boolean()
18+
.description('Attempt to hard reset to upstream\'s latest commit'),
19+
20+
assignees: Joi.array().items(Joi.string())
21+
.description('Assignees for the pull requests'),
22+
23+
reviewers: Joi.array().items(Joi.string())
24+
.description('Reviewers for the pull requests'),
25+
26+
label: Joi.string()
27+
.description('Label for the pull requests')
28+
}
29+
30+
const ruleSchema = Joi.object().keys({
31+
upstream: fields.upstream.required(),
32+
autoMerge: fields.autoMerge.default(false),
33+
autoMergeHardReset: fields.autoMerge.default(false)
34+
}).options({ stripUnknown: true }).required()
35+
36+
const schema = Joi.object().keys({
37+
version: fields.version.required(),
38+
rules: Joi.object().pattern(/[^\s:]+/, ruleSchema).required(),
39+
assignees: fields.assignees.default([]),
40+
reviewers: fields.assignees.default([]),
41+
label: fields.label.default('sync-up :arrow_up_down:')
42+
}).options({ stripUnknown: true }).required()
43+
44+
module.exports = schema

0 commit comments

Comments
 (0)