Skip to content

Commit 79115ae

Browse files
committed
workflow to build release binaries
1 parent a82d0ea commit 79115ae

File tree

3 files changed

+254
-0
lines changed

3 files changed

+254
-0
lines changed

.github/workflows/release.yml

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Release
2+
3+
permissions:
4+
contents: write
5+
6+
on:
7+
push:
8+
tags:
9+
- "mdr-v[0-9]*"
10+
11+
jobs:
12+
create-release:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v4
16+
- uses: taiki-e/create-gh-release-action@v1
17+
with:
18+
prefix: "mdr"
19+
# (required) GitHub token for creating GitHub Releases.
20+
token: ${{ secrets.GITHUB_TOKEN }}
21+
22+
upload-assets:
23+
needs: create-release
24+
strategy:
25+
matrix:
26+
include:
27+
- target: x86_64-unknown-linux-gnu
28+
os: ubuntu-latest
29+
- target: x86_64-apple-darwin
30+
os: macos-latest
31+
- target: x86_64-pc-windows-msvc
32+
os: windows-latest
33+
runs-on: ${{ matrix.os }}
34+
steps:
35+
- uses: actions/checkout@v4
36+
- uses: taiki-e/upload-rust-binary-action@v1
37+
with:
38+
# (required) Comma-separated list of binary names
39+
# (non-extension portion of filename) to build and upload.
40+
# Note that glob pattern is not supported yet.
41+
bin: mdr,mdr-toml
42+
# (optional) Target triple, default is host triple.
43+
# This is optional but it is recommended that this always be set to
44+
# clarify which target you are building for if macOS is included in
45+
# the matrix because GitHub Actions changed the default architecture
46+
# of macos-latest since macos-14.
47+
target: ${{ matrix.target }}
48+
# (optional) On which platform to distribute the `.tar.gz` file.
49+
# [default value: unix]
50+
# [possible values: all, unix, windows, none]
51+
tar: unix
52+
# (optional) On which platform to distribute the `.zip` file.
53+
# [default value: windows]
54+
# [possible values: all, unix, windows, none]
55+
zip: windows
56+
# (required) GitHub token for uploading assets to GitHub Releases.
57+
token: ${{ secrets.GITHUB_TOKEN }}
58+
59+
make-table:
60+
runs-on: ubuntu-latest
61+
needs: upload-assets
62+
steps:
63+
- uses: actions/checkout@v4
64+
65+
- name: Set up Python
66+
uses: actions/setup-python@v4
67+
with:
68+
python-version: '3.x' # Specify the version of Python to use
69+
70+
- name: Install dependencies
71+
run: python -m pip install --upgrade pip && pip install requests chardet
72+
73+
- name: Run Python script
74+
run: |
75+
python .github/workflows/update_release_table.py ${{ github.ref_name }}
76+
env:
77+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/rust.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Rust
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
env:
10+
CARGO_TERM_COLOR: always
11+
12+
jobs:
13+
build:
14+
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- uses: actions/checkout@v4
19+
- name: Build
20+
run: cargo build --verbose
21+
- name: Run tests
22+
run: cargo test --verbose
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
#!/usr/bin/env python3
2+
3+
import requests
4+
import argparse
5+
import os
6+
import re
7+
import json
8+
from typing import NamedTuple, Optional, TextIO
9+
10+
# GitHub repository details
11+
REPO = "TravisWheelerLab/mdr"
12+
API_URL = f"https://api.github.com/repos/{REPO}/releases"
13+
14+
15+
class ReleaseInfo(NamedTuple):
16+
""" Release info """
17+
os: str
18+
arch: str
19+
20+
21+
class Args(NamedTuple):
22+
""" Command-line args """
23+
version: str
24+
json: Optional[TextIO]
25+
26+
27+
# --------------------------------------------------
28+
def get_args() -> Args:
29+
parser = argparse.ArgumentParser(
30+
description="Update a specific release in GitHub."
31+
)
32+
33+
parser.add_argument(
34+
"version", help="The tag name of the release to update"
35+
)
36+
37+
parser.add_argument(
38+
"-j",
39+
"--json",
40+
type=argparse.FileType("rt"),
41+
help="Local JSON file"
42+
)
43+
44+
args = parser.parse_args()
45+
46+
return Args(version=args.version, json=args.json)
47+
48+
49+
# --------------------------------------------------
50+
def main() -> None:
51+
args = get_args()
52+
releases = get_releases_data(args.json)
53+
54+
if release := find_release_by_version(releases, args.version):
55+
print("Release '{}' has {} assets".format(args.version, len(release["assets"])))
56+
markdown_table = generate_markdown_table(release)
57+
update_release_body(release["id"], markdown_table)
58+
print(f"Release '{args.version}' updated successfully.")
59+
else:
60+
print(f"Release version '{args.version}' not found.")
61+
62+
63+
# --------------------------------------------------
64+
def get_releases_data(file: Optional[TextIO]):
65+
if file:
66+
return json.loads(file.read())
67+
68+
headers = {
69+
"Authorization": f'token {os.getenv("GITHUB_TOKEN")}',
70+
"Accept": "application/vnd.github.v3+json",
71+
}
72+
response = requests.get(API_URL, headers=headers)
73+
response.raise_for_status()
74+
return response.json()
75+
76+
77+
# --------------------------------------------------
78+
def find_release_by_version(releases, version):
79+
for release in releases:
80+
if release["tag_name"] == version:
81+
return release
82+
return None
83+
84+
85+
# --------------------------------------------------
86+
def extract_os_arch_from_filename(filename) -> Optional[ReleaseInfo]:
87+
pattern = re.compile(r"^(.+)(?:\.tar\.gz|\.zip)$")
88+
89+
if match := pattern.search(filename):
90+
stem = match.group(1)
91+
_, arch, os = stem.split("-", 2)
92+
93+
if os == "macos-latest" or os == "apple-darwin":
94+
os = "MacOS"
95+
elif os == "ubuntu-latest":
96+
os = "Ubuntu"
97+
elif re.search("linux", os):
98+
os = "Linux"
99+
elif re.search("windows", os):
100+
os = "Windows"
101+
102+
if arch == "x64" or arch == "x86_64":
103+
arch = "Intel/AMD 64-bit"
104+
elif arch == "386":
105+
arch = "Intel/AMD 32-bit"
106+
elif arch == "arm64":
107+
if os == "MacOS":
108+
arch = "M1/M2/M3 (ARM 64-bit)"
109+
else:
110+
arch = "ARM 64-bit"
111+
elif arch == "arm":
112+
arch = "ARM 32-bit"
113+
114+
return ReleaseInfo(os, arch)
115+
116+
117+
# --------------------------------------------------
118+
def generate_markdown_table(release) -> str:
119+
table = "### Release Assets\n"
120+
table += "| OS | Architecture | Link |\n"
121+
table += "|---------|----------|-------------|\n"
122+
123+
for asset in release["assets"]:
124+
if info := extract_os_arch_from_filename(asset["name"]):
125+
print(">>> Asset {}".format(asset["name"]))
126+
download_url = asset["browser_download_url"]
127+
table += f"| {info.os} | {info.arch} | [Download]({download_url}) |\n"
128+
129+
# Add note about Mac binary signing restriction
130+
table += (
131+
"\n***(For Macs) To address the Mac binary signing restriction, use the following command:\n"
132+
"\n```\n"
133+
"sudo xattr -dr com.apple.quarantine <path to file>/mdr\n"
134+
"```\n"
135+
)
136+
137+
return table
138+
139+
140+
# --------------------------------------------------
141+
def update_release_body(release_id, new_body):
142+
headers = {
143+
"Authorization": f'token {os.getenv("GITHUB_TOKEN")}',
144+
"Accept": "application/vnd.github.v3+json",
145+
}
146+
update_url = f"https://api.github.com/repos/{REPO}/releases/{release_id}"
147+
data = {"body": new_body}
148+
149+
response = requests.patch(update_url, headers=headers, json=data)
150+
response.raise_for_status()
151+
152+
153+
# --------------------------------------------------
154+
if __name__ == "__main__":
155+
main()

0 commit comments

Comments
 (0)