Skip to content

Instantly share code, notes, and snippets.

@mryhryki
Last active April 5, 2022 22:43
Show Gist options
  • Save mryhryki/d901e54ccf07145a556975ae4d1be016 to your computer and use it in GitHub Desktop.
Save mryhryki/d901e54ccf07145a556975ae4d1be016 to your computer and use it in GitHub Desktop.
1年以上更新がないIssueを抽出するスクリプト

1年以上更新がないIssueを抽出するスクリプト

.idea
node_modules
package-lock.json
const fetch = require('node-fetch')
const Organization = "Connehito"
const FirstCount = 100;
const getGitHubToken = () => {
const envVar = process.env.GITHUB_ACCESS_TOKEN
if (envVar) {
return envVar
}
throw new Error('GITHUB_ACCESS_TOKEN が設定されていません。')
}
const getAfterQuery = (nextToken) => {
if (!nextToken) {
return ''
}
return `, after: "${nextToken}"`
}
const fetchRepositories = async (nextToken = null) => {
const result = await fetchGitHubV4(`
{
organization(login: "${Organization}") {
repositories(first: ${FirstCount}${getAfterQuery(nextToken)}) {
nodes {
name
isArchived
}
edges{
cursor
}
}
}
}
`)
const {nodes, edges} = result.data.organization.repositories
const repositories = nodes.filter(({isArchived}) => !isArchived).map(({name}) => name)
const lastCursor = (edges[FirstCount - 1] || {}).cursor || null
return {
repositories,
nextToken: lastCursor,
}
}
const fetchAllRepositories = async () => {
let nextToken = null
const repositories = []
do {
const result = await fetchRepositories(nextToken)
result.repositories.forEach((repository) => {
repositories.push(repository)
})
nextToken = result.nextToken
} while(nextToken != null)
return repositories
}
const fetchOpenIssues =async (repository, nextToken = null) => {
const result = await fetchGitHubV4(
`
query($repository: String!){
organization(login: "Connehito") {
repository(name: $repository) {
issues(first: 100, states: [OPEN]${getAfterQuery(nextToken)}) {
nodes {
url
title
updatedAt
}
edges {
cursor
}
}
}
}
}
`,
{repository}
)
const {nodes, edges} = result.data.organization.repository.issues
const repositories = nodes
const lastCursor = (edges[FirstCount - 1] || {}).cursor || null
return {
repositories,
nextToken: lastCursor,
}
}
const fetchAllOpenIssues = async (repository) => {
let nextToken = null
const issues = []
do {
const result = await fetchOpenIssues(repository, nextToken)
result.repositories.forEach((issue) => {
issues.push(issue)
})
nextToken = result.nextToken
} while(nextToken != null)
return issues
}
const fetchGitHubV4 = async (query, variables = {}) => {
const response = await fetch('https://api.github.com/graphql', {
method: 'post',
headers: {
Authorization: `Bearer ${getGitHubToken()}`,
},
body: JSON.stringify({query, variables}),
})
return response.json()
}
module.exports = {
fetchAllRepositories,
fetchAllOpenIssues,
}
const dayjs = require('dayjs')
const {fetchAllRepositories, fetchAllOpenIssues} = require('./github_api')
const baseDate = dayjs().add(-1, 'year')
const issueFilter = (targetDatetime) => dayjs(targetDatetime) < baseDate
const main = async () => {
const repositories = await fetchAllRepositories()
const issues = await Promise.all(
repositories.map(async (repository) => {
const issues = (await fetchAllOpenIssues(repository)).filter(({updatedAt}) => issueFilter(updatedAt))
return {repository, issues}
})
)
// console.log(JSON.stringify(issues, null, 2))
issues.forEach(({repository, issues}) => {
if (issues.length === 0) {
return
}
console.log('## %s', repository)
console.log('')
issues.forEach(({title, url}) => {
console.log('- [%s](%s)', title, url)
})
console.log('')
})
}
main();
{
"name": "github_issues",
"private": true,
"scripts": {
"start": "node index.js"
},
"author": "hyiromori",
"license": "MIT",
"dependencies": {
"dayjs": "^1.10.4",
"node-fetch": "^2.6.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment