Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automation of github release and tag, and publish to pypi #1414

Closed
wants to merge 36 commits into from
Closed
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
73fd52e
test automation of release version
andrewelamb Apr 17, 2024
2f65364
test automation of release version
andrewelamb Apr 17, 2024
704c250
test automation of release version
andrewelamb Apr 17, 2024
6c0752b
test automation of release version
andrewelamb Apr 17, 2024
ffd5a9c
add step to get repo tags
andrewelamb Apr 17, 2024
ab4e6fd
add step to get repo tags
andrewelamb Apr 17, 2024
584e334
add step to get repo tags
andrewelamb Apr 17, 2024
50da9b0
add poetry shell to its own line
andrewelamb Apr 17, 2024
1239710
revert
andrewelamb Apr 17, 2024
61574b4
use env for tags
andrewelamb Apr 17, 2024
26009b8
capitalize tags
andrewelamb Apr 17, 2024
45e0e5e
set TAGS to output data var
andrewelamb Apr 17, 2024
c96ee2e
remove type checking
andrewelamb Apr 17, 2024
094ede2
handle json conversion
andrewelamb Apr 17, 2024
23ec6aa
add re.match to match for standard release
andrewelamb Apr 17, 2024
6764e6c
add v to re.match
andrewelamb Apr 17, 2024
684671c
temp commit
andrewelamb Apr 18, 2024
a7232d9
add github scripts dir
andrewelamb Apr 18, 2024
205efd1
split constructions and setting of release version into two steps
andrewelamb Apr 18, 2024
fab3357
add step for creatign release
andrewelamb Apr 18, 2024
bfdc529
refactor functions, add tests
andrewelamb Apr 18, 2024
c84a4cf
nothing
andrewelamb Apr 18, 2024
02ecf17
added back in publish step
andrewelamb Apr 18, 2024
780f239
turn of pypi publishing check
andrewelamb Apr 18, 2024
9e5aebf
change name of test release
andrewelamb Apr 18, 2024
97b7fb3
final commits to restore previous functionality
andrewelamb Apr 18, 2024
4b2cafd
remove python form comment
andrewelamb Apr 18, 2024
137b984
remove old script
andrewelamb Apr 18, 2024
93e17f2
fix documentation
andrewelamb Apr 18, 2024
de208fb
correct the current toml version
andrewelamb Apr 18, 2024
42e3651
restore toml file
andrewelamb Apr 18, 2024
fcfacfb
Merge branch 'develop' into develop-fds-1613-release-automation
andrewelamb Apr 18, 2024
5227211
add back in tag trigger
andrewelamb Apr 22, 2024
f1dffa6
two publish workflows
andrewelamb Apr 26, 2024
7d7bd2f
linglings suggestions
andrewelamb Apr 26, 2024
5711679
improve tag regex
andrewelamb Apr 26, 2024
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
122 changes: 122 additions & 0 deletions .github/workflows/publish_main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Publish to PyPI
on:
push:
branches: ['main']

jobs:
pypi_release:
runs-on: ubuntu-latest
env:
POETRY_VERSION: 1.3.0
steps:
- name: Get list of tags
uses: octokit/[email protected]
id: get_latest_release
with:
route: GET /repos/${{ github.repository }}/git/matching-refs/tags
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
#----------------------------------------------
# check-out repo and set-up python
#----------------------------------------------
- name: Check out repository
uses: actions/checkout@v2

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}

#----------------------------------------------
# install & configure poetry
#----------------------------------------------
- name: Install Poetry
run: |
curl -sSL https://install.python-poetry.org \
| python3 - --version ${{ env.POETRY_VERSION }};
poetry config virtualenvs.create true;
poetry config virtualenvs.in-project true;

#----------------------------------------------
# load cached venv if cache exists
#----------------------------------------------
- name: Load cached venv
id: cached-poetry-dependencies
uses: actions/cache@v2
with:
path: .venv
key: venv-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}

#----------------------------------------------
# install dependencies and root project
#----------------------------------------------
- name: Install dependencies and root project
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --all-extras

#----------------------------------------------
# Construct release version
#----------------------------------------------
- name: Construct release version
id: release_version
run: |
VAR=$(poetry run python3.10 github_scripts/construct_release_version.py)
echo "RELEASE_VERSION=$VAR" >> "$GITHUB_OUTPUT"
shell: sh
env:
TAGS: ${{ steps.get_latest_release.outputs.data }}

#----------------------------------------------
# Create release
#----------------------------------------------

- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.release_version.outputs.RELEASE_VERSION }}
release_name: ${{ steps.release_version.outputs.RELEASE_VERSION }}
draft: false
prerelease: false

#----------------------------------------------
# Set release version
#----------------------------------------------
- name: Set release version
run: |
poetry run python3 github_scripts/update_toml_version.py
shell: sh
env:
RELEASE_VERSION: ${{ steps.release_version.outputs.RELEASE_VERSION }}

#----------------------------------------------
# publish to pypi
#----------------------------------------------
- name: Publish package to Pypi
id: publish-to-pypi
env:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
PYPI_USERNAME: __token__
run: |
poetry publish --build --username $PYPI_USERNAME --password $PYPI_TOKEN

#----------------------------------------------
# post a message to slack
#----------------------------------------------

- name: Post to a Slack channel
if: steps.publish-to-pypi.outcome == 'success'
id: slack
uses: slackapi/[email protected]
with:
# Slack channel id, channel name, or user id to post message.
# See also: https://api.slack.com/methods/chat.postMessage#channels
# You can pass in multiple channels to post to by providing a comma-delimited list of channel IDs.
# ibc-fair-data channel and data-curator-schematic channel
channel-id: 'C050YD75QRL,C01ANC02U59'
# For posting a simple plain text message
slack-message: "Schematic has just been released. Check out new version: ${{ github.ref_name }}"
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Publish to PyPI
on:
push:
tags:
- 'v[1-9][0-9].[0-9]+.[0-9]+'
- 'v[1-9][0-9].[0-9]+.[0-9].[a-z]+'
branches: [main]
Copy link
Contributor

Choose a reason for hiding this comment

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

Even if we want to keep two workflows, can we clean up this workflow more? Here, this workflow will still get triggered because branches: [main]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh maybe I misunderstand how this works, but I thought this would require both the branch to be main and the tag to match. Otherwise this would have been triggered before every time we pushed to main right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I went ahead and removed that line


jobs:
Expand Down Expand Up @@ -114,4 +114,4 @@ jobs:
# For posting a simple plain text message
slack-message: "Schematic has just been released. Check out new version: ${{ github.ref_name }}"
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
andrewelamb marked this conversation as resolved.
Show resolved Hide resolved
Empty file added github_scripts/__init__.py
Empty file.
24 changes: 24 additions & 0 deletions github_scripts/construct_release_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""
This is a command line script meant to be used by a github action.
It constructs the current release tag using todays date, and the number of releases
already this month.
For example the first release of January 2024 would be 24.1.1 and the second would be 24.1.2
It assumes there is an environmental variable set called TAGS that contains the tag
information from the repo.
"""
import os

from github_scripts.utils import (
get_date_strings,
get_number_of_versions_this_month,
get_version_list_from_tags,
)

tag_string = os.getenv("TAGS")
assert isinstance(tag_string, str)

year, month = get_date_strings()
version_list = get_version_list_from_tags(tag_string)
num_tags_this_month = get_number_of_versions_this_month(version_list, year, month)

print (f"{year}.{month}.{num_tags_this_month + 1}")
20 changes: 20 additions & 0 deletions github_scripts/update_toml_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"""
This is a command line script meant to be used by a github action.
It modifies the pyproject.toml file to have the current release version.
Poetry use the toml version as the version it publishes to pypi.
It assumes there is an environmental variable set called RELEASE_VERSION
that contains the release version to use.
"""

import os
import toml

RELEASE_VERSION = os.getenv("RELEASE_VERSION")
assert isinstance(RELEASE_VERSION, str)

data = toml.load("pyproject.toml")
data['tool']['poetry']['version']=RELEASE_VERSION
print('the version number of this release is: ', RELEASE_VERSION)

with open("pyproject.toml",'w', encoding="utf-8") as file:
toml.dump(data, file)
75 changes: 75 additions & 0 deletions github_scripts/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""Util functions for github scripts"""

import os
from datetime import date
import re
from typing import Optional
import json


def get_date_strings(todays_date:Optional[date]=None) -> tuple[str, str]:
"""Gets todays year and month in form as strings

Args:
todays_date (Optional[date], optional): Defaults to None.

Returns:
tuple[str, str]: The year and month in two digit form ie. ("24", "12")
"""
if todays_date is None:
todays_date = date.today()
todays_year = str(todays_date.year)[-2:]
todays_month = str(todays_date.month)
return todays_year, todays_month

def get_version_list_from_tags(tag_string:str) -> list[str]:
"""Gets the versions from a list fo tags in string form

Args:
tag_string (str): A json in string form that contians tag information such as:
'[
{
"ref": "refs/tags/v24.2.1",
},
"ref": "refs/tags/v24.2.1-beta",
}
]'

Returns:
list[str]: A list of versions from each tag
"""
tag_dict_list = json.loads(tag_string)
assert isinstance(tag_dict_list, list)
for tag in tag_dict_list:
assert isinstance(tag, dict)
assert "ref" in tag
assert isinstance(tag["ref"], str)
ref_list: list[str] = [tag_dict["ref"] for tag_dict in tag_dict_list]
version_list = [os.path.basename(ref) for ref in ref_list]
return version_list


def get_number_of_versions_this_month(
version_list: list[str],
todays_year: str,
todays_month: str
) -> int:
"""
This takes a list of version and returns the number of tags from this month.

Args:
version_list (list[str]): A list of tag version such as "v24.2.1"
todays_year(str): todays year as a two digit string ie. 2024: "24"
todays_month(str): todays month as a one or two digit string ie. December: "12"

Returns:
int: Ther number of tags already released this month
"""
tags_this_month:int = 0
for version in version_list:
if re.match("^v[0-9]+\.[0-9]+\.[0-9]+$", version):
version = version[1:]
version_year, version_month, version_number = version.split(".")
if version_year == todays_year and version_month == todays_month:
tags_this_month = max(int(version_number), tags_this_month)
return tags_this_month
13 changes: 0 additions & 13 deletions override_version.py

This file was deleted.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,4 @@ markers = [
empty_token: marks api tests that \
send empty credentials in the request
"""
]
]
45 changes: 45 additions & 0 deletions tests/test_github_scripts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
""" Tests for github scripts"""

from datetime import date

from github_scripts.utils import (
get_date_strings,
get_version_list_from_tags,
get_number_of_versions_this_month,
)

def test_get_date_string() -> None:
"""Tests get_date_string"""
year, month = get_date_strings()
assert len(year) == 2
assert 100 > int(year) >= 0
assert 3 > len(month) > 0
assert 13 > int(month) > 0

year, month = get_date_strings(date(2020, 1, 1))
year = "20"
month = "1"

year, month = get_date_strings(date(1999, 12, 10))
year = "99"
month = "12"

def test_get_version_list_from_tags() -> None:
"""Tests get_version_list_from_tags"""
tags = (
'['
'{"ref": "x/x/v24.1.1"},'
'{"ref": "x/x/v24.1.2"},'
'{"ref": "x/x/v24.1.3"}'
']'
)
assert get_version_list_from_tags(tags) == ["v24.1.1", "v24.1.2", "v24.1.3"]

def test_get_number_of_versions_this_month() -> None:
"""Tests get_number_of_versions_this_month"""
versions = ["v24.1.1", "v24.1.2", "v24.1.3"]
assert get_number_of_versions_this_month(versions, "24", "1") == 3
assert get_number_of_versions_this_month(versions, "23", "1") == 0
assert get_number_of_versions_this_month(versions, "24", "0") == 0
versions2 = ["24.1.1", "v24.1.1-dev"]
assert get_number_of_versions_this_month(versions2, "24", "1") == 0
Loading