diff --git a/.github/ISSUE_TEMPLATE/release-pulse.md b/.github/ISSUE_TEMPLATE/release-pulse.md new file mode 100644 index 0000000..1e5cd0c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/release-pulse.md @@ -0,0 +1,46 @@ +--- +name: "⏰ Time for release" +about: Coordinate the release of Z2JH and dependencies +labels: release-pulse +title: "Time for release - {{ date | date('dddd, MMMM Do') }}" +--- + +This is a release reminder to help JupyterHub team members coordinate a new **Z2JH release**. This issue will be closed at the end of the week. + +## Dependencies +Z2JH dependencies that might need a release too. + +| Repository | Commits since latest version | Release Instructions | +| --- | --- | --- | +| [jupyterhub/oauthenticator](https://github.com/jupyterhub/oauthenticator) | {{INSERT LATEST OAUTHENTICATOR COMMITS HERE}} | [RELEASE.md](https://github.com/jupyterhub/oauthenticator/blob/master/RELEASE.md) | +| [jupyterhub/kubespawner](https://github.com/jupyterhub/kubespawner) | {{INSERT LATEST KUBESPAWNER COMMITS HERE}} | [RELEASE.md](https://github.com/jupyterhub/kubespawner/blob/master/RELEASE.md) | +| [jupyterhub/configurable-http-proxy](https://github.com/jupyterhub/configurable-http-proxy) | {{INSERT LATEST CHP COMMITS HERE}} | [RELEASE.md](https://github.com/jupyterhub/configurable-http-proxy/blob/main/RELEASE.md) | + +### Make a release of dependencies + +- **OAuthenticator** + - [ ] A new release has been made 🎉 + - [ ] No new PRs had been merged, or a release isn't warranted for some reason +- **Kubespawner** + - [ ] A new release has been made 🎉 + - [ ] No new PRs had been merged, or a release isn't warranted for some reason +- **Configurable-Http-Proxy** + - [ ] A new release has been made 🎉 + - [ ] No new PRs had been merged, or a release isn't warranted for some reason + +## Z2JH +Details and checklist to help coordinate the next Z2JH release. + +### Details +Details about current state of Z2JH. + +| Latest version | Commits since latest version | +| --- | --- | +| {{INSERT LATEST RELEASE HERE}} | {{INSERT LATEST COMMITS HERE}} | + +**Currently open PRs:** +{{INSERT PRS HERE}} + +### Make a release ([release instructions](https://github.com/jupyterhub/zero-to-jupyterhub-k8s/blob/master/RELEASE.md#release-process)) +- [ ] **Changelog updated** +- [ ] **Tag pushed** diff --git a/.github/workflows/close-release-pulse.yaml b/.github/workflows/close-release-pulse.yaml new file mode 100644 index 0000000..365b737 --- /dev/null +++ b/.github/workflows/close-release-pulse.yaml @@ -0,0 +1,15 @@ +# From https://github.com/marketplace/actions/close-matching-issues +name: Close a release pulse reminder after 7 days it was created +on: + schedule: + # At 00:00 on day-of-month 8 in every 3rd month (ref: https://crontab.guru/#0_0_8_*/3_*) + - cron: "0 0 8 */3 *" + +jobs: + close-release-pulse-issue: + runs-on: ubuntu-latest + steps: + - uses: lee-dohm/close-matching-issues@v2 + with: + query: 'label:release-pulse' + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/create-release-pulse.yaml b/.github/workflows/create-release-pulse.yaml new file mode 100644 index 0000000..813afee --- /dev/null +++ b/.github/workflows/create-release-pulse.yaml @@ -0,0 +1,30 @@ +# From https://github.com/JasonEtco/create-an-issue +name: Open a release pulse reminder issue every three months +on: + schedule: + # At 00:00 on day-of-month 1 in every 3rd month (ref https://crontab.guru/#0_0_1_*/3_*) + - cron: "0 0 1 */3 *" + + workflow_dispatch: + +jobs: + open-release-pulse-issue: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + # Install dependencies + - name: Set up Python 3.7 + uses: actions/setup-python@v1 + with: + python-version: 3.7 + + - name: Install ghapi + run: | + pip install ghapi + + - name: Post release pulse md + env: + ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }} + run: | + python scripts/post_release_pulse.py diff --git a/script/post_release_pulse.py b/script/post_release_pulse.py new file mode 100644 index 0000000..a5a7e13 --- /dev/null +++ b/script/post_release_pulse.py @@ -0,0 +1,77 @@ +from ghapi.all import GhApi +from datetime import date +from ghapi.actions import github_token +from packaging import version +from base64 import b64decode + +def get_latest_tag(org, repo): + tags = api.repos.list_tags(org, repo) + versions = [tag.name for tag in tags] + versions.sort(key=version.parse, reverse=True) + return versions[0] + +# On GitHub Actions "ACCESS_TOKEN" should be a personal access token with r/w permissions to *other* repos +token = github_token() if "ACCESS_TOKEN" not in os.environ else os.environ["ACCESS_TOKEN"] + +# Initialize the GH API +api = GhApi(token=token) + +# The base template is defined here: https://github.com/jupyterhub/team-compass/blob/release-pulse-issue/.github/ISSUE_TEMPLATE/release-pulse.md +# It has placeholders for lists of PRs, commits and latests version and these will be automatically filled in below, then a new issue will be created. +template = api.repos.get_content("jupyterhub", "team-compass", ".github/ISSUE_TEMPLATE/release-pulse.md", "release-pulse-issue") +template = b64decode(template.content).decode("utf-8") + +# This removes the header bracketed by --- +template = "---".join(template.split("---")[2:]).strip() + +# Z2JH +latest_tag = get_latest_tag("jupyterhub", "zero-to-jupyterhub-k8s") +template = template.replace( + "{{INSERT LATEST RELEASE HERE}}", + latest_tag +) + +unreleased_commits = f"https://github.com/jupyterhub/zero-to-jupyterhub-k8s/compare/{latest_tag}...main" +template = template.replace( + "{{INSERT LATEST COMMITS HERE}}", + unreleased_commits +) + +pulls = api.pulls.list("jupyterhub", "zero-to-jupyterhub-k8s", state="open") +if pulls: + need_merge = "\n".join([f"* [{pull.title}]({pull.html_url})" for pull in pulls])+ "\n\n" +template = template.replace( + "{{INSERT PRS HERE}}", + need_merge +) + +# Dependencies +# OAuthenticator +latest_tag = get_latest_tag("jupyterhub", "oauthenticator") +unreleased_commits = f"https://github.com/jupyterhub/oauthenticator/compare/{latest_tag}...master" +template = template.replace( + "{{INSERT LATEST OAUTHENTICATOR COMMITS HERE}}", + unreleased_commits +) + +# Kubespawner +latest_tag = get_latest_tag("jupyterhub", "kubespawner") +unreleased_commits = f"https://github.com/jupyterhub/kubespawner/compare/{latest_tag}...master" +template = template.replace( + "{{INSERT LATEST KUBESPAWNER COMMITS HERE}}", + unreleased_commits +) + +# CHP +latest_tag = get_latest_tag("jupyterhub", "configurable-http-proxy") + +unreleased_commits = f"https://github.com/jupyterhub/configurable-http-proxy/compare/{latest_tag}...main" +template = template.replace( + "{{INSERT LATEST CHP COMMITS HERE}}", + unreleased_commits +) + +# Create an issue +resp = api.issues.create("jupyterhub", "team-compass", title=f"Time for release - {date.today():%b %d, %Y}", body=template, labels=["release-pulse"]) +url = f"https://github.com/{resp.url.split('repos/')[-1]}" +print(f"Finished posting release issue to {url} !")