Skip to content
82 changes: 82 additions & 0 deletions .github/workflows/release_notes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
name: Create release notes changelog
on:
release:
types: [created]
Comment on lines +1 to +4

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a github actions that will do:

ruby GithubIssueStats.rb > changelog.txt

Then a python script that will locate the created release, and basically do current_release.body += changelog

This is untested since it will not run until it's on develop and I create a release, but I have tested it that the python script works fine.


jobs:
release-notes:
name: Create changelog
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- uses: actions/setup-ruby@v1
with:
ruby-version: 2.5

- uses: actions/setup-python@v2
with:
python-version: 3.8

- name: Create changelog using GitHubIssueStats.rb
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ruby ./developer/ruby/GitHubIssueStats.rb > changelog.txt

- name: Upload changelog to release body
shell: python
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
import json
import requests

OWNER_REPO = "${{ github.repository }}" # 'openstudiocoalition/OpenStudioApplication'
GITHUB_REF = os.environ['GITHUB_REF'] # v1.1.0-rc1
GITHUB_TOKEN = os.environ['GITHUB_TOKEN'] # Secret oauth token (40 chars)

HEADERS = {
"Content-Type": 'application/json',
"Accept": 'application/vnd.github.antiope-preview+json',
"Authorization": "Bearer {}".format(GITHUB_TOKEN),
"User-Agent": 'github-actions-changelog'
}

# Just to be safe
TAG_NAME = GITHUB_REF.replace('refs/tags/', '')

print(f"{OWNER_REPO=}, {GITHUB_REF=}, {TAG_NAME=}")

def get_release_by_tag_name(owner_repo, tag_name):

query_url = f"https://api.github.com/repos/{owner_repo}/releases/tags/{tag_name}"

r = requests.get(query_url, headers=HEADERS)
if r.status_code != requests.codes.ok:
http_error_msg = ("{} Error: {} for url: "
"{}.\n{}".format(r.status_code, r.reason, r.url, json.dumps(r.json(), indent=4, sort_keys=True)))
raise requests.exceptions.HTTPError(http_error_msg, response=r)

return r.json()

data = get_release_by_tag_name(owner_repo=OWNER_REPO, tag_name=TAG_NAME)

release_id = data['id']

with open('changelog.txt', 'r') as f:
changelog = f.read()

new_body = data['body'] + "\n\n## Changelog\n\n" + changelog

patch_data = {
"body": new_body,
}

patch_url = f"https://api.github.com/repos/{OWNER_REPO}/releases/{release_id}"

r = requests.patch(patch_url, data=json.dumps(patch_data), headers=HEADERS)
if r.status_code != requests.codes.ok:
r.raise_for_status()
151 changes: 151 additions & 0 deletions developer/ruby/GitHubIssueStats.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
require 'github_api'
require 'date'
require 'yaml'

# Get the begin date, by finding the last major/minor (X.Y.0) release
# that is at least a week old
def get_begin_date_and_previous_tag()
a_week_ago = Time.now - (60*60*24*7)

@github.repos.releases.list(owner: @repo_owner,
repo: @repo).each_page do |page|
page.each do |release|
next if release.tag_name !~ /^v\d\.\d\.0$/
release_date = Time.parse(release.created_at)
next if release_date > a_week_ago
# This is perhaps unecessary since we match to a tag in vX.Y.0 format
# already but it doesn't hurt
next if release.prerelease
next if release.draft
STDERR.puts "Found previous major/minor release: #{release.tag_name}, #{release_date}"
return release_date, " (#{release.tag_name})"
end
end
STDERR.puts "Cannot find previous release, setting time to 2005"
return Time.new(2005, 01, 01), ""
end

def get_num(issue)
issue.html_url.split('/')[-1].to_i
end

def get_issue_num(issue)
"\##{get_num(issue)}"
end

def get_html_url(issue)
issue.html_url
end

def get_title(issue)
issue.title
end

def print_issue(issue)
is_feature = false
issue.labels.each {|label| is_feature = true if label.name == "Enhancement Request"}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the right label, it works and I see from "Improved"


if is_feature
"- :heavy_plus_sign: [#{get_issue_num(issue)}]( #{get_html_url(issue)} ), #{get_title(issue)}"
else
"- :heavy_check_mark: [#{get_issue_num(issue)}]( #{get_html_url(issue)} ), #{get_title(issue)}"
end
end


@repo_owner = 'openstudiocoalition'
@repo = 'OpenStudioApplication'
@end_date = Time.now
@github = nil

if !ENV['GITHUB_TOKEN'].nil?
token = ENV['GITHUB_TOKEN']
@github = Github.new oauth_token: token
elsif File.exists?(Dir.home + '/github_config.yml')
github_options = YAML.load_file(Dir.home + '/github_config.yml')
token = github_options['oauth_token']
@github = Github.new oauth_token: token
else
STDERR.puts "Github Token not found"
@github = Github.new
end

@begin_date, @prev_tag = get_begin_date_and_previous_tag()

totalOpenIssues = Array.new
totalOpenPullRequests = Array.new
newIssues = Array.new
closedIssues = Array.new
acceptedPullRequests = Array.new

# Process Open Issues
results = -1
page = 1
while (results != 0)
resp = @github.issues.list user: @repo_owner, repo: @repo,
:sort => 'created',
:direction => 'asc',
:state => 'open',
:per_page => 100,
:page => page
results = resp.length
resp.env[:body].each do |issue, index|
created = Time.parse(issue.created_at)
if !issue.has_key?(:pull_request)
totalOpenIssues << issue
if created >= @begin_date && created <= @end_date
newIssues << issue
end
else
totalOpenPullRequests << issue
end
end

page = page + 1
end

# Process Closed Issues
results = -1
page = 1
while (results != 0)
resp = @github.issues.list user: @repo_owner, repo: @repo,
:sort => 'created',
:direction => 'asc',
:state => 'closed',
:per_page => 100,
:page => page
results = resp.length
resp.env[:body].each do |issue, index|
created = Time.parse(issue.created_at)
closed = Time.parse(issue.closed_at)
if !issue.has_key?(:pull_request)
if created >= @begin_date && created <= @end_date
newIssues << issue
end
if closed >= @begin_date && closed <= @end_date
closedIssues << issue
end
elsif closed >= @begin_date && closed <= @end_date
acceptedPullRequests << issue
end
end

page = page + 1
end

closedIssues.sort! {|x,y| get_num(x) <=> get_num(y)}
newIssues.sort! {|x,y| get_num(x) <=> get_num(y)}
acceptedPullRequests.sort! {|x,y| get_num(x) <=> get_num(y)}
totalOpenPullRequests.sort! {|x,y| get_num(x) <=> get_num(y)}

puts "\n**Date Range: #{@begin_date.to_date.iso8601}**#{@prev_tag} - **#{@end_date.to_date.iso8601}:**"
puts "\n**New Issues: #{newIssues.length}** (" + newIssues.map{|issue| get_issue_num(issue)}.join(', ') + ')'

puts "\n**Closed Issues: #{closedIssues.length}**" # (" + closedIssues.map{|issue| get_issue_num(issue)}.join(', ') + ')'
closedIssues.each{|issue| puts print_issue(issue)}

puts "\n**Accepted Pull Requests: #{acceptedPullRequests.length}**" # (" + acceptedPullRequests.map{|issue| get_issue_num(issue)}.join(', ') + ')'
acceptedPullRequests.each{|issue| puts print_issue(issue)}

puts "\n**Total Open Issues: #{totalOpenIssues.length}** (" + totalOpenIssues.map{|issue| get_issue_num(issue)}.join(', ') + ')'
puts "\n**Total Open Pull Requests: #{totalOpenPullRequests.length}** (" + totalOpenPullRequests.map{|issue| get_issue_num(issue)}.join(', ') + ')'