Share the article
Subscribe for updates
Sardine needs the contact information you provide to us to contact you about our products and services.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.

Automating Release Notes with Asana and Github

At sardine, we iterate fast on building new features. As our team scales, keeping various stakeholders including account managers, integration managers and technical support informed is critical for us. Additionally, for compliance and security reasons, it’s critical for us to have written changelog and approval history of each deployment.

In this blog post, we explain how we implemented a script to automate release note generation.

We use github as a code repository, asana for task tracking and slack for communication. Our release script automatically pulls information from github and asana, and then posts information to the slack.

Deployment process

Get release information

First step of the script is to get release versions from the remote server. Since we always deploy to sandbox before the production deployment via CD, we can easily get version we want to release (what is in sandbox) and version we last deployed (what is in production)

def get_release():url = ""res = requests.get(url)return res.headers['X-Version-Id']

Get information about changes

Using the release version (git commit SHA) from the previous step, we can now get all the relevant PRs and list of related asana tasks. We ask all developers to include a link to asana task in PR descriptions, so we can get list of asana tasks from github. For this step, the script first get list of commits via “git log” command, and then we call the github API. Earlier version of this script used GH CLI, but we have migrated to the REST APIs because the CLI doesn’t support fine-grained access tokens.

def get_all_prs(repo, previous, release): result = subprocess.getstatusoutput(f"git log --pretty=format:'%h - %an, %ar : %s' {previous}..{release}") pr_numbers = re.findall("#([0-9]+)", result[1]) pr_numbers = list(map(int, pr_numbers)) github_pat = os.getenv('GITHUB_PAT', None) url = '' + repo + '/pulls?state=closed&direction=desc&per_page=100' prs = [] # get 500 PRs for page in range(1, 6):   prs += requests.get(     url + "&page=" + str(page),     headers={"Authorization":"Bearer " + github_pat}   ).json() return list(filter(lambda pr: pr['number'] in pr_numbers, prs))

Generate deploy ticket

Now we have all the relevant information so we can create a deploy approval ticket that captures all related changes. One thing we found useful ways to ask everyone to follow conventional commit (put prefixes like “fix”, “feat”). That way the script can automatically categorize changes into new features, bugfixes and so on.

release notes

Slack notifications

When deploy approval ticket is generated it automatically post to slack for approval requests. Our deploy script also notify when deployment completes, so stakeholders can easily follow what is planned to deploy and what is being deployed.

slack notification

Convert auto-generated release notes to public release notes

Lastly, while the automated release notes provide instant benefit to internal semi-technical stakeholders like product managers, it is not easy for external consumption. Our awesome product managers convert nice external facing release notes.

We also publish our script here so you don’t have to reinvent the wheel. Automate everything and focus on building interesting stuff!

Share the article
About the author
Kazuki Nishiura
Head of Engineering