-
-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add an action that extends awards.csv on PR merges (#1931)
- Loading branch information
1 parent
4e113c2
commit 5de9d92
Showing
2 changed files
with
133 additions
and
0 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,20 @@ | ||
name: extend-awards | ||
run-name: Extending awards | ||
on: | ||
push: | ||
branches: | ||
- master | ||
jobs: | ||
if_merged: | ||
if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v4 | ||
- uses: actions/setup-python@v5 | ||
with: | ||
python-version: '3.13' | ||
- run: pip install requests | ||
- run: python extend-awards.py '${{ toJson(github) }}' | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
- uses: peter-evans/create-pull-request@v7 |
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,113 @@ | ||
import json, os, re, requests, sys | ||
|
||
difficulties = {'good-first-issue':20000,'easy':100000,'medium':250000,'medium-hard':500000,'hard':1000000} | ||
priorities = {'low':0.5,'medium':1.5,'high':2,'urgent':3} | ||
ignored = ['huumn', 'ekzyis'] | ||
fn = 'awards.csv' | ||
|
||
sess = requests.Session() | ||
headers = {'Authorization':'Bearer %s' % os.getenv('GITHUB_TOKEN') } | ||
awards = [] | ||
|
||
def getIssue(n): | ||
url = 'https://api.github.com/repos/stackernews/stacker.news/issues/' + n | ||
r = sess.get(url, headers=headers) | ||
j = json.loads(r.text) | ||
return j | ||
|
||
def findIssueInPR(j): | ||
p = re.compile('(#|https://github.com/stackernews/stacker.news/issues/)([0-9]+)') | ||
for m in p.finditer(j['title']): | ||
return m.group(2) | ||
if not 'body' in j or j['body'] is None: | ||
return | ||
for s in j['body'].split('\n'): | ||
for m in p.finditer(s): | ||
return m.group(2) | ||
|
||
def addAward(user, kind, pr, issue, difficulty, priority, count, amount): | ||
if amount >= 1000000 and amount % 1000000 == 0: | ||
amount = str(int(amount / 1000000)) + 'm' | ||
elif amount >= 1000 and amount % 1000 == 0: | ||
amount = str(int(amount / 1000)) + 'k' | ||
for a in awards: | ||
if a[0] == user and a[1] == kind and a[2] == pr: | ||
print('found existing entry %s' % a) | ||
if a[8] != amount: | ||
print('warning: amount %s != %s' % (a[8], amount)) | ||
return | ||
if count < 1: | ||
count = '' | ||
addr = '???' | ||
for a in awards: | ||
if a[0] == user and a[9] != '???': | ||
addr = a[9] | ||
print('adding %s,%s,%s,%s,%s,%s,%s,,%s,%s,???' % (user, kind, pr, issue, difficulty, priority, count, amount, addr)) | ||
with open(fn, 'a') as f: | ||
print('%s,%s,%s,%s,%s,%s,%s,,%s,%s,???' % (user, kind, pr, issue, difficulty, priority, count, amount, addr), file=f) | ||
|
||
def countReviews(pr): | ||
url = 'https://api.github.com/repos/stackernews/stacker.news/issues/%s/timeline' % pr | ||
r = sess.get(url, headers=headers) | ||
j = json.loads(r.text) | ||
count = 0 | ||
for e in j: | ||
if e['event'] == 'reviewed' and e['state'] == 'changes_requested': | ||
count += 1 | ||
return count | ||
|
||
def checkPR(pr): | ||
i = getIssue(pr) | ||
if not 'pull_request' in i or not 'merged_at' in i['pull_request']: | ||
print('pr %s is not a merged pull request' % pr) | ||
return | ||
print('pr %s' % pr) | ||
n = findIssueInPR(i) | ||
if not n: | ||
print('pr %s does not solve an issue' % pr) | ||
return | ||
print('solves issue %s' % n) | ||
j = getIssue(n) | ||
difficulty = '' | ||
amount = 0 | ||
priority = '' | ||
multiplier = 1 | ||
for l in j['labels']: | ||
for d in difficulties: | ||
if l['name'] == 'difficulty:' + d: | ||
difficulty = d | ||
amount = difficulties[d] | ||
for p in priorities: | ||
if l['name'] == 'priority:' + p: | ||
priority = p | ||
multiplier = priorities[p] | ||
if amount * multiplier <= 0: | ||
print('issue gives no award') | ||
return | ||
count = countReviews(pr) | ||
if count >= 10: | ||
print('too many reviews, no award') | ||
return | ||
if count > 0: | ||
print('%d reviews, %d%% reduction' % (count, count * 10)) | ||
award = amount * multiplier * (10 - count) / 10 | ||
print('award is %d' % award) | ||
if i['user']['login'] not in ignored: | ||
addAward(i['user']['login'], 'pr', '#' + pr, '#' + n, difficulty, priority, count, award) | ||
if j['user']['login'] not in ignored: | ||
count = 0 | ||
addAward(j['user']['login'], 'issue', '#' + pr, '#' + n, difficulty, priority, count, int(award / 10)) | ||
|
||
with open(fn, 'r') as f: | ||
for s in f: | ||
s = s.split('\n')[0] | ||
awards.append(s.split(',')) | ||
|
||
j = json.loads(sys.argv[1]) | ||
for c in j['event']['commits']: | ||
m = re.search('\\(#([0-9]+)\\)$', c['message'].split('\n')[0]) | ||
if m: | ||
checkPR(m.group(1)) | ||
exit(0) | ||
print('no PR found in commit') | ||
|