-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build: update content when upstream changes
This commit adds support to update the content when there is a change upstream by: - Adding a webhook handler to redirect `push` and `release` events from `electron/electron` to this repo. - Adding a GitHub action that responds to `repository_dispatch` events comming from the previous webhook. More information can be found in #19 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Fix #19
- Loading branch information
Showing
22 changed files
with
3,050 additions
and
66 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
GITHUB_TOKEN= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
name: 'Update docs' | ||
|
||
on: | ||
repository_dispatch: | ||
types: [doc_changes] | ||
|
||
jobs: | ||
update-docs: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-node@v2 | ||
with: | ||
node-version: '14' | ||
- name: Install dependencies | ||
run: 'yarn' | ||
- name: Update pinned version | ||
run: 'yarn update-pinned-version ${{ github.event.client_payload.sha }}' | ||
- name: 'Prebuild' | ||
run: 'yarn prebuild' | ||
- name: 'Create PR' | ||
run: 'yarn process-docs-changes' | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
node_modules | ||
.docusaurus | ||
.DS_Store | ||
.env | ||
.vscode/settings.json | ||
build/ | ||
content/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. | ||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp | ||
|
||
// List of extensions which should be recommended for users of this workspace. | ||
"recommendations": ["esbenp.prettier-vscode", "orta.vscode-jest"], | ||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace. | ||
"unwantedRecommendations": [] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
GITHUB_TOKEN= | ||
SECRET= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//@ts-check | ||
require('dotenv-safe').config(); | ||
const express = require('express'); | ||
const app = express(); | ||
const port = process.env.PORT || 3000; | ||
|
||
const { addWebhooks } = require('./routes/webhook'); | ||
|
||
const start = async ()=>{ | ||
await addWebhooks(app); | ||
|
||
app.get('/', (req, res) => { | ||
res.send(`There's nothing here!`); | ||
}); | ||
|
||
app.listen(port, () => { | ||
console.log(`API listening on port ${port}`); | ||
}); | ||
}; | ||
|
||
start(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "webhook", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"start": "node index.js", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [], | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"dotenv-safe": "^8.2.0", | ||
"express": "^4.17.1", | ||
"got": "^11.8.2", | ||
"latest-version": "^5.1.0", | ||
"semver": "^6.3.0" | ||
}, | ||
"devDependencies": { | ||
"@octokit/webhooks-types": "^3.71.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
//@ts-check | ||
|
||
const semver = require('semver'); | ||
const got = require('got').default; | ||
|
||
const { | ||
getLatestInformation, | ||
isEvent, | ||
verifyIntegrity, | ||
} = require('../utils/utils'); | ||
|
||
const SOURCE_REPO = 'electron/electron'; | ||
const TARGET_REPO = 'electron/electronjs.org-new'; | ||
const GITHUB_TOKEN = process.env.GITHUB_TOKEN; | ||
const DOC_CHANGES_TYPE = 'doc_changes'; | ||
|
||
/** | ||
* @typedef CustomRepositoryDispatchPayload | ||
* @property {string} sha | ||
*/ | ||
|
||
/** | ||
* Sends a `repository_dispatch` event top the given repo `target` | ||
* with the type `doc_changes` and the given commit `sha` as part | ||
* of the payload. | ||
* @param {string} target The repo to send the event to | ||
* @param {string} sha The commit's SHA | ||
*/ | ||
const sendRepositoryDispatchEvent = async (target, sha) => { | ||
return got.post(`https://github.com/${target}/dispatches`, { | ||
headers: { | ||
Authorization: `Token ${GITHUB_TOKEN}`, | ||
Accept: 'application/vnd.github.v3+json', | ||
'Content-Type': 'application/json', | ||
}, | ||
body: { | ||
event_type: DOC_CHANGES_TYPE, // This is the only event we can send for now | ||
client_payload: { | ||
sha, | ||
}, | ||
}, | ||
}); | ||
}; | ||
|
||
/** | ||
* Verifies there is at least one file added, modified, or removed | ||
* in the given `folder` through all the commits associated in the | ||
* push. | ||
* @param {import('@octokit/webhooks-types').PushEvent} pushEvent | ||
* @param {string} folder | ||
*/ | ||
const areFilesInFolderChanged = (pushEvent, folder) => { | ||
const isInPath = (file) => { | ||
return file.includes(folder); | ||
}; | ||
|
||
const { commits } = pushEvent; | ||
|
||
return commits.some((commit) => { | ||
return ( | ||
commit.modified.some(isInPath) || | ||
commit.added.some(isInPath) || | ||
commit.removed.some(isInPath) | ||
); | ||
}); | ||
}; | ||
|
||
/** | ||
* Handler for the GitHub webhook `push` event. | ||
* @param {import('express').Request} req | ||
* @param {import('express').Response} res | ||
*/ | ||
const pushHandler = async (req, res) => { | ||
const { branch } = await getLatestInformation(); | ||
const ref = `refs/heads/${branch}`; | ||
|
||
/** @type {import('@octokit/webhooks-types').PushEvent} */ | ||
const payload = JSON.parse(req.body); | ||
|
||
if ( | ||
payload.ref === ref && | ||
payload.repository.full_name === SOURCE_REPO && | ||
areFilesInFolderChanged(payload, 'docs') | ||
) { | ||
console.log('Send notification'); | ||
|
||
await sendRepositoryDispatchEvent(TARGET_REPO, payload.after); | ||
|
||
return res.status(200).send('Handled'); | ||
} | ||
|
||
return res.status(200).send('Unhandled'); | ||
}; | ||
|
||
/** | ||
* Handler for the GitHub webhook `release` event. | ||
* The payload will be processed only if the release | ||
* payload is for the stable branch. | ||
* @param {import('express').Request} req | ||
* @param {import('express').Response} res | ||
*/ | ||
const releaseHandler = async (req, res) => { | ||
/** @type {import('@octokit/webhooks-types').ReleaseEvent} */ | ||
const payload = JSON.parse(req.body); | ||
|
||
const { release } = await getLatestInformation(); | ||
|
||
// Tags can be v14.0.0-nightly.20210504, v13.0.0-beta.21, v10.4.5, etc. | ||
// We only want to process the stable ones, i.e.: v10.4.5 | ||
// so we remove the initial `v` and we "clean it". If the cleaned | ||
// string is the same as before, then it's a stable release. | ||
// We also check that the new release is greater or equal than the | ||
// published npm version. There can be 30-120s delay between a GitHub | ||
// release and an npm one. | ||
const tag = payload.release.tag_name.replace(/^v/, ''); | ||
const isStable = semver.clean(tag) === tag; | ||
|
||
if ( | ||
payload.action === 'released' && | ||
!payload.release.draft && | ||
!payload.release.prerelease && | ||
isStable && | ||
semver.gte(tag, release) | ||
) { | ||
await sendRepositoryDispatchEvent( | ||
TARGET_REPO, | ||
payload.release.target_commitish | ||
); | ||
|
||
return res.status(200).send('Handled'); | ||
} else { | ||
return res.status(200).send('Undhandled'); | ||
} | ||
}; | ||
|
||
/** | ||
* Adds the right handles for the `push` and `release` | ||
* webhooks to the given `app`. | ||
* @param {import('express').Application} app | ||
*/ | ||
const addWebhooks = async (app) => { | ||
app.post('/webhook/push', isEvent('push'), verifyIntegrity, pushHandler); | ||
app.post( | ||
'/webhook/release', | ||
isEvent('release'), | ||
verifyIntegrity, | ||
releaseHandler | ||
); | ||
}; | ||
|
||
module.exports = { | ||
addWebhooks, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
const crypto = require('crypto'); | ||
const latestVersion = require('latest-version'); | ||
|
||
const SECRET = process.env.SECRET; | ||
|
||
let _stableVersion = ''; | ||
let _stableBranch = ''; | ||
let _lastUpdated = 0; | ||
const CACHE_TIMEOUT = 5 * 60 * 1000; // we cache version for 5 minutes | ||
|
||
const getLatestInformation = async () => { | ||
const now = Date.now(); | ||
if (now - _lastUpdated > CACHE_TIMEOUT) { | ||
_stableVersion = await latestVersion('electron'); | ||
_stableBranch = _stableVersion.replace(/\.d+\.\d+$/, '-x-y'); | ||
} | ||
|
||
return { | ||
version: _stableVersion, | ||
branch: _stableBranch, | ||
}; | ||
}; | ||
|
||
/** | ||
* Middleware to validate the handler is the right one | ||
* for the received event. | ||
* @param {string} event | ||
* @returns {import('express').Handler} | ||
*/ | ||
const isEvent = (event) => { | ||
return (req, res, next) => { | ||
if (req.header('X-GitHub-Event') !== event) { | ||
return res.status(400).send(); | ||
} | ||
|
||
return next(); | ||
}; | ||
}; | ||
|
||
/** | ||
* Middleware to verify the integraty of a GitHub webhook | ||
* by using the `X-Hub-Signature`, the secret and the payload. | ||
* @param {import('express').Request} req | ||
* @param {import('express').Response} res | ||
* @param {import('express').NextFunction} next | ||
*/ | ||
const verifyIntegrity = (req, res, next) => { | ||
if (!req.header('X-Hub-Signature')) { | ||
console.error(`Missing singature in payload`); | ||
return res.status(400).send(`Missing singature in payload`); | ||
} | ||
|
||
try { | ||
const signature = Buffer.from(req.header('X-Hub-Signature')); | ||
const payload = req.body; | ||
|
||
const signedPayload = Buffer.from( | ||
`sha1=${crypto.createHmac('sha1', SECRET).update(payload).digest('hex')}` | ||
); | ||
|
||
if (signature.length !== signedPayload.length) { | ||
console.error(`Invalid signature`); | ||
return res.status(400).send(`Invalid signature`); | ||
} | ||
|
||
if (!crypto.timingSafeEqual(signature, signedPayload)) { | ||
console.error(`Invalid signature`); | ||
return res.status(400).send(`Invalid signature`); | ||
} | ||
next(); | ||
} catch (e) { | ||
console.error(`Invalid signature`); | ||
return res.status(400).send(`Invalid signature`); | ||
} | ||
}; | ||
|
||
module.exports = { | ||
isEvent, | ||
verifyIntegrity, | ||
getLatestInformation, | ||
}; |
Oops, something went wrong.