-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from gitgitgadget/trigger-sync-ref-workflow-runs
Automatically trigger the `sync-ref` workflow runs on pushes to `git/git`
- Loading branch information
Showing
14 changed files
with
474 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,7 @@ | ||
module.exports = (fn, fallback) => { | ||
try { | ||
return fn() | ||
} catch (e) { | ||
return fallback | ||
} | ||
} |
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,14 @@ | ||
const getInstallationAccessToken = async (context, installation_id) => { | ||
const { gitHubAPIRequestAsApp } = require('./github-api-request-as-app') | ||
const answer = await gitHubAPIRequestAsApp( | ||
context, | ||
'POST', | ||
`/app/installations/${installation_id}/access_tokens`) | ||
if (answer.error) throw answer.error | ||
if (answer.token) return answer.token | ||
throw new Error(`Unhandled response:\n${JSON.stringify(answer, null, 2)}`) | ||
} | ||
|
||
module.exports = { | ||
getInstallationAccessToken | ||
} |
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,14 @@ | ||
const getInstallationIdForRepo = async (context, owner, repo) => { | ||
const { gitHubAPIRequestAsApp } = require('./github-api-request-as-app') | ||
const answer = await gitHubAPIRequestAsApp( | ||
context, | ||
'GET', | ||
`/repos/${owner}/${repo}/installation` | ||
) | ||
if (answer.error) throw answer.error | ||
return answer.id | ||
} | ||
|
||
module.exports = { | ||
getInstallationIdForRepo | ||
} |
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,47 @@ | ||
const gitHubAPIRequestAsApp = async (context, requestMethod, requestPath, body) => { | ||
const header = { | ||
"alg": "RS256", | ||
"typ": "JWT" | ||
} | ||
|
||
const now = Math.floor(new Date().getTime() / 1000) | ||
|
||
const payload = { | ||
// issued at time, 60 seconds in the past to allow for clock drift | ||
iat: now - 60, | ||
// JWT expiration time (10 minute maximum) | ||
exp: now + (10 * 60), | ||
// GitHub App's identifier | ||
iss: process.env['GITHUB_APP_ID'] | ||
} | ||
|
||
const toBase64 = (obj) => Buffer.from(JSON.stringify(obj), "utf-8").toString("base64url") | ||
const headerAndPayload = `${toBase64(header)}.${toBase64(payload)}` | ||
|
||
const privateKey = process.env['GITHUB_APP_PRIVATE_KEY'].replaceAll('\\n', '\n') | ||
|
||
const crypto = require('crypto') | ||
const signer = crypto.createSign("RSA-SHA256") | ||
signer.update(headerAndPayload) | ||
const signature = signer.sign({ | ||
key: privateKey | ||
}, "base64url") | ||
|
||
const token = `${headerAndPayload}.${signature}` | ||
|
||
const { httpsRequest } = require('./https-request') | ||
return await httpsRequest( | ||
context, | ||
null, | ||
requestMethod, | ||
requestPath, | ||
body, | ||
{ | ||
Authorization: `Bearer ${token}`, | ||
} | ||
) | ||
} | ||
|
||
module.exports = { | ||
gitHubAPIRequestAsApp | ||
} |
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,11 @@ | ||
const gitHubAPIRequest = async (context, token, method, requestPath, payload) => { | ||
const { httpsRequest } = require('./https-request') | ||
const headers = token ? { Authorization: `Bearer ${token}` } : null | ||
const answer = await httpsRequest(context, null, method, requestPath, payload, headers) | ||
if (answer.error) throw answer.error | ||
return answer | ||
} | ||
|
||
module.exports = { | ||
gitHubAPIRequest | ||
} |
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,88 @@ | ||
const gently = require('./gently') | ||
|
||
const httpsRequest = async (context, hostname, method, requestPath, body, headers) => { | ||
headers = { | ||
'User-Agent': 'GitForWindowsHelper/0.0', | ||
Accept: 'application/json', | ||
...headers || {} | ||
} | ||
if (body) { | ||
if (typeof body === 'object') body = JSON.stringify(body) | ||
headers['Content-Type'] = 'application/json' | ||
headers['Content-Length'] = body.length | ||
} | ||
const options = { | ||
port: 443, | ||
hostname: hostname || 'api.github.com', | ||
method: method || 'GET', | ||
path: requestPath, | ||
headers | ||
} | ||
return new Promise((resolve, reject) => { | ||
try { | ||
const https = require('https') | ||
const req = https.request(options, res => { | ||
res.on('error', e => reject(e)) | ||
|
||
if (res.statusCode === 204) resolve({ | ||
statusCode: res.statusCode, | ||
statusMessage: res.statusMessage, | ||
headers: res.headers | ||
}) | ||
|
||
const chunks = [] | ||
res.on('data', data => chunks.push(data)) | ||
res.on('end', () => { | ||
const json = Buffer.concat(chunks).toString('utf-8') | ||
if (res.statusCode > 299) { | ||
reject({ | ||
statusCode: res.statusCode, | ||
statusMessage: res.statusMessage, | ||
requestMethod: options.method, | ||
requestPath: options.path, | ||
body: json, | ||
json: gently(() => JSON.parse(json)) | ||
}) | ||
return | ||
} | ||
try { | ||
resolve(JSON.parse(json)) | ||
} catch (e) { | ||
reject(`Invalid JSON: ${json}`) | ||
} | ||
}) | ||
}) | ||
req.on('error', err => reject(err)) | ||
if (body) req.write(body) | ||
req.end() | ||
} catch (e) { | ||
reject(e) | ||
} | ||
}) | ||
} | ||
|
||
const doesURLReturn404 = async url => { | ||
const match = url.match(/^https:\/\/([^/]+?)(:\d+)?(\/.*)?$/) | ||
if (!match) throw new Error(`Could not parse URL ${url}`) | ||
|
||
const https = require('https') | ||
const options = { | ||
method: 'HEAD', | ||
host: match[1], | ||
port: Number.parseInt(match[2] || '443'), | ||
path: match[3] || '/' | ||
} | ||
return new Promise((resolve, reject) => { | ||
https.request(options, res => { | ||
if (res.error) reject(res.error) | ||
else if (res.statusCode === 404) resolve(true) | ||
else if (res.statusCode === 200) resolve(false) | ||
else reject(`Unexpected statusCode: ${res.statusCode}`) | ||
}).end() | ||
}) | ||
} | ||
|
||
module.exports = { | ||
httpsRequest, | ||
doesURLReturn404 | ||
} |
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,48 @@ | ||
const https = require('https'); | ||
|
||
const triggerAzurePipeline = async (token, organization, project, buildDefinitionId, sourceBranch, parameters) => { | ||
const auth = Buffer.from('PAT:' + token).toString('base64'); | ||
const headers = { | ||
'Accept': 'application/json; api-version=5.0-preview.5; excludeUrls=true', | ||
'Authorization': 'Basic ' + auth, | ||
}; | ||
const json = JSON.stringify({ | ||
'definition': { 'id': buildDefinitionId }, | ||
'sourceBranch': sourceBranch, | ||
'parameters': JSON.stringify(parameters), | ||
}); | ||
headers['Content-Type'] = 'application/json'; | ||
headers['Content-Length'] = Buffer.byteLength(json); | ||
|
||
const requestOptions = { | ||
host: 'dev.azure.com', | ||
port: '443', | ||
path: `/${organization}/${project}/_apis/build/builds?ignoreWarnings=false&api-version=5.0-preview.5`, | ||
method: 'POST', | ||
headers: headers | ||
}; | ||
|
||
return new Promise((resolve, reject) => { | ||
const handleResponse = (res) => { | ||
res.setEncoding('utf8'); | ||
var response = ''; | ||
res.on('data', (chunk) => { | ||
response += chunk; | ||
}); | ||
res.on('end', () => { | ||
resolve(JSON.parse(response)); | ||
}); | ||
res.on('error', (err) => { | ||
reject(err); | ||
}) | ||
}; | ||
|
||
const request = https.request(requestOptions, handleResponse); | ||
request.write(json); | ||
request.end(); | ||
}); | ||
} | ||
|
||
module.exports = { | ||
triggerAzurePipeline | ||
} |
Oops, something went wrong.