Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ audioscrobbler
Autoloaded
automator
backreference
basehead
Bizau
blankslate
blog
Expand All @@ -32,7 +33,6 @@ datapoints
dded
dependabot
deployer
dessant
destructuring
Dexcom
dflag
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
ref: master
- name: Format code
run: |
npm install -g dprint
npm i
mkdir -v -p /home/runner/.cache/dprint/cache
npx dprint fmt --config .github/config/dprint.json
- name: Publish formatted code
Expand All @@ -38,7 +38,6 @@ jobs:
git add --all
git commit -m "chore: code formatting"
git push
set -e

# Update plugins and template indexes, along with README.md
update-indexes:
Expand Down
5 changes: 0 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,6 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Format code with dprint
run: |
npm install -g dprint
mkdir -v -p /home/runner/.cache/dprint/cache
npx dprint fmt --config .github/config/dprint.json
- name: Build gh-metrics/metrics:${{ github.head_ref || 'master' }}
env:
GIT_REF: ${{ github.head_ref || 'master' }}
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ dist
.tern-port

# User settings
settings.json
/settings.json

# Community templates
source/templates/.community
Expand Down
5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"dprint.dprint"
]
}
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"editor.defaultFormatter": "dprint.dprint"
}
2 changes: 1 addition & 1 deletion source/.eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ rules:
# Code integrity
no-unsafe-optional-chaining: error
no-duplicate-imports: error
eqeqeq: error
eqeqeq: [error, "always", {null: "ignore"}]

# Code simplicity
max-depth: [error, 10]
Expand Down
4 changes: 2 additions & 2 deletions source/plugins/achievements/list/organizations.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export default async function({list, login, data, computed, imports, graphql, qu

//Managers
{
const value = organization.projects.totalCount
const unlock = organization.projects.nodes?.shift()
const value = organization.projectsV2.totalCount
const unlock = organization.projectsV2.nodes?.shift()

list.push({
title: "Managers",
Expand Down
4 changes: 2 additions & 2 deletions source/plugins/achievements/list/users.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ export default async function({list, login, data, computed, imports, graphql, qu

//Manager
{
const value = user.projects.totalCount
const unlock = user.projects.nodes?.shift()
const value = user.projectsV2.totalCount
const unlock = user.projectsV2.nodes?.shift()

list.push({
title: "Manager",
Expand Down
71 changes: 51 additions & 20 deletions source/plugins/activity/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,44 @@ export default async function({login, data, rest, q, account, imports}, {enabled
}
console.debug(`metrics/compute/${login}/plugins > activity > ${events.length} events loaded`)

const payloadTypesToCustomTypes = {
CommitCommentEvent: "comment",
CreateEvent: "ref/create",
DeleteEvent: "ref/delete",
ForkEvent: "fork",
GollumEvent: "wiki",
IssueCommentEvent: "comment",
IssuesEvent: "issue",
MemberEvent: "member",
PublicEvent: "public",
PullRequestEvent: "pr",
PullRequestReviewEvent: "review",
PullRequestReviewCommentEvent: "comment",
PushEvent: "push",
ReleaseEvent: "release",
WatchEvent: "star",
}

//Extract activity events
const activity = (await Promise.all(
events
.filter(({actor}) => account === "organization" ? true : actor.login?.toLocaleLowerCase() === login.toLocaleLowerCase())
.filter(({created_at}) => Number.isFinite(days) ? new Date(created_at) > new Date(Date.now() - days * 24 * 60 * 60 * 1000) : true)
.filter(event => visibility === "public" ? event.public : true)
.map(async ({type, payload, actor: {login: actor}, repo: {name: repo}, created_at}) => {
//See https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/github-event-types
.map(event => ({event, customType: payloadTypesToCustomTypes[event.type]}))
.filter(({customType}) => !!customType) //Ignore events with an unknown type
.filter(({customType}) => filter.includes("all") || filter.includes(customType)) //Filter events based on user preference
.map(({event}) => event) //Discard customType, it will be re-assigned
.map(async ({type, payload, actor: {login: actor}, repo: {name: repo}, created_at}) => { //See https://docs.github.com/en/free-pro-team@latest/developers/webhooks-and-events/github-event-types
const timestamp = new Date(created_at)
if (!imports.filters.repo(repo, skipped))
return null

//Get custom type from the previously declared mapping, so that it acts as a single source of truth
const customType = payloadTypesToCustomTypes[type]
if (!customType)
throw new Error(`Missing event mapping for type: ${type}`)

switch (type) {
//Commented on a commit
case "CommitCommentEvent": {
Expand All @@ -56,27 +83,27 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {comment: {user: {login: user}, commit_id: sha, body: content}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "comment", on: "commit", actor, timestamp, repo, content: await imports.markdown(content, {mode: markdown, codelines}), user, mobile: null, number: sha.substring(0, 7), title: ""}
return {type: customType, on: "commit", actor, timestamp, repo, content: await imports.markdown(content, {mode: markdown, codelines}), user, mobile: null, number: sha.substring(0, 7), title: ""}
}
//Created a git branch or tag
case "CreateEvent": {
const {ref: name, ref_type: type} = payload
return {type: "ref/create", actor, timestamp, repo, ref: {name, type}}
return {type: customType, actor, timestamp, repo, ref: {name, type}}
}
//Deleted a git branch or tag
case "DeleteEvent": {
const {ref: name, ref_type: type} = payload
return {type: "ref/delete", actor, timestamp, repo, ref: {name, type}}
return {type: customType, actor, timestamp, repo, ref: {name, type}}
}
//Forked repository
case "ForkEvent": {
const {forkee: {full_name: forked}} = payload
return {type: "fork", actor, timestamp, repo, forked}
return {type: customType, actor, timestamp, repo, forked}
}
//Wiki changes
case "GollumEvent": {
const {pages} = payload
return {type: "wiki", actor, timestamp, repo, pages: pages.map(({title}) => title)}
return {type: customType, actor, timestamp, repo, pages: pages.map(({title}) => title)}
}
//Commented on an issue
case "IssueCommentEvent": {
Expand All @@ -85,7 +112,7 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {issue: {user: {login: user}, title, number}, comment: {body: content, performed_via_github_app: mobile}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "comment", on: "issue", actor, timestamp, repo, content: await imports.markdown(content, {mode: markdown, codelines}), user, mobile, number, title}
return {type: customType, on: "issue", actor, timestamp, repo, content: await imports.markdown(content, {mode: markdown, codelines}), user, mobile, number, title}
}
//Issue event
case "IssuesEvent": {
Expand All @@ -94,7 +121,7 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {action, issue: {user: {login: user}, title, number, body: content}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "issue", actor, timestamp, repo, action, user, number, title, content: await imports.markdown(content, {mode: markdown, codelines})}
return {type: customType, actor, timestamp, repo, action, user, number, title, content: await imports.markdown(content, {mode: markdown, codelines})}
}
//Activity from repository collaborators
case "MemberEvent": {
Expand All @@ -103,11 +130,11 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {member: {login: user}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "member", actor, timestamp, repo, user}
return {type: customType, actor, timestamp, repo, user}
}
//Made repository public
case "PublicEvent": {
return {type: "public", actor, timestamp, repo}
return {type: customType, actor, timestamp, repo}
}
//Pull requests events
case "PullRequestEvent": {
Expand All @@ -116,14 +143,14 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {action, pull_request: {user: {login: user}, title, number, body: content, additions: added, deletions: deleted, changed_files: changed, merged}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "pr", actor, timestamp, repo, action: (action === "closed") && (merged) ? "merged" : action, user, title, number, content: await imports.markdown(content, {mode: markdown, codelines}), lines: {added, deleted}, files: {changed}}
return {type: customType, actor, timestamp, repo, action: (action === "closed") && (merged) ? "merged" : action, user, title, number, content: await imports.markdown(content, {mode: markdown, codelines}), lines: {added, deleted}, files: {changed}}
}
//Reviewed a pull request
case "PullRequestReviewEvent": {
const {review: {state: review}, pull_request: {user: {login: user}, number, title}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "review", actor, timestamp, repo, review, user, number, title}
return {type: customType, actor, timestamp, repo, review, user, number, title}
}
//Commented on a pull request
case "PullRequestReviewCommentEvent": {
Expand All @@ -132,31 +159,36 @@ export default async function({login, data, rest, q, account, imports}, {enabled
const {pull_request: {user: {login: user}, title, number}, comment: {body: content, performed_via_github_app: mobile}} = payload
if (!imports.filters.text(user, ignored))
return null
return {type: "comment", on: "pr", actor, timestamp, repo, content: await imports.markdown(content, {mode: markdown, codelines}), user, mobile, number, title}
return {type: customType, on: "pr", actor, timestamp, repo, content: await imports.markdown(content, {mode: markdown, codelines}), user, mobile, number, title}
}
//Pushed commits
case "PushEvent": {
let {size, commits, ref} = payload
let {size, ref, head, before} = payload
const [owner, repoName] = repo.split("/")

const res = await rest.repos.compareCommitsWithBasehead({owner, repo: repoName, basehead: `${before}...${head}`})
let {commits} = res.data

commits = commits.filter(({author: {email}}) => imports.filters.text(email, ignored))
if (!commits.length)
return null
if (commits.slice(-1).pop()?.message.startsWith("Merge branch "))
if (commits.slice(-1).pop()?.commit.message.startsWith("Merge branch "))
commits = commits.slice(-1)
return {type: "push", actor, timestamp, repo, size, branch: ref.match(/refs.heads.(?<branch>.*)/)?.groups?.branch ?? null, commits: commits.reverse().map(({sha, message}) => ({sha: sha.substring(0, 7), message}))}
return {type: customType, actor, timestamp, repo, size, branch: ref.match(/refs.heads.(?<branch>.*)/)?.groups?.branch ?? null, commits: commits.reverse().map(({sha, message}) => ({sha: sha.substring(0, 7), message}))}
}
//Released
case "ReleaseEvent": {
if (!["published"].includes(payload.action))
return null
const {action, release: {name, tag_name, prerelease, draft, body: content}} = payload
return {type: "release", actor, timestamp, repo, action, name: name || tag_name, prerelease, draft, content: await imports.markdown(content, {mode: markdown, codelines})}
return {type: customType, actor, timestamp, repo, action, name: name || tag_name, prerelease, draft, content: await imports.markdown(content, {mode: markdown, codelines})}
}
//Starred a repository
case "WatchEvent": {
if (!["started"].includes(payload.action))
return null
const {action} = payload
return {type: "star", actor, timestamp, repo, action}
return {type: customType, actor, timestamp, repo, action}
}
//Unknown event
default: {
Expand All @@ -166,7 +198,6 @@ export default async function({login, data, rest, q, account, imports}, {enabled
}),
))
.filter(event => event)
.filter(event => filter.includes("all") || filter.includes(event.type))
.slice(0, limit)

//Results
Expand Down
11 changes: 9 additions & 2 deletions source/plugins/habits/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ export default async function({login, data, rest, imports, q, account}, {enabled
const patches = [
...await Promise.allSettled(
commits
.flatMap(({payload}) => payload.commits)
.filter(({author}) => data.shared["commits.authoring"].filter(authoring => author?.login?.toLocaleLowerCase().includes(authoring) || author?.email?.toLocaleLowerCase().includes(authoring) || author?.name?.toLocaleLowerCase().includes(authoring)).length)
.flatMap(({payload}) => payload?.commits ?? [])
.filter(commit => {
if (commit == null || typeof commit !== "object")
return false
const author = commit?.author
if (!author)
return false
return data.shared["commits.authoring"].filter(authoring => author?.login?.toLocaleLowerCase().includes(authoring) || author?.email?.toLocaleLowerCase().includes(authoring) || author?.name?.toLocaleLowerCase().includes(authoring)).length
})
.map(async commit => (await rest.request(commit)).data.files),
),
]
Expand Down
7 changes: 3 additions & 4 deletions source/plugins/languages/analyzer/analyzer.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//Imports
import core from "@actions/core"
import fs from "fs/promises"
import os from "os"
import paths from "path"
import git from "simple-git"
import { filters } from "../../../app/metrics/utils.mjs"
import core from "@actions/core"

/**Analyzer */
export class Analyzer {
Expand Down Expand Up @@ -89,9 +89,8 @@ export class Analyzer {
const {repo, branch, path} = this.parse(repository)
let token

if (process.env.GITHUB_ACTIONS) {
if (process.env.GITHUB_ACTIONS)
token = core.getInput("token")
}

let url = /^https?:\/\//.test(repo) ? repo : `https://${token}@github.com/${repo}`
try {
Expand Down Expand Up @@ -183,4 +182,4 @@ export class Analyzer {
debug(message) {
return console.debug(`metrics/compute/${this.login}/plugins > languages > ${this.constructor.name.replace(/([a-z])([A-Z])/, (_, a, b) => `${a} ${b.toLocaleLowerCase()}`).toLocaleLowerCase()} > ${message}`)
}
}
}
Loading
Loading