Skip to content

Commit 0dafc77

Browse files
authored
ci: update release flow and publish list.json (paritytech#276)
This pull request adds changes described in **this comment**: - `.github/scripts/json_generator.py` - a small script that generates several json files for different platforms. - [generate_versions.yml](https://github.com/paritytech/revive/compare/as-release-json?expand=1#diff-2aee05b96020ac60943e6dfcb30597e53898f31542aeb570468b970d9a13a5a6) - the workflow that runs when release is published, creates info.json files and pushes them into resolc-bin repo - `js/build.js` is adjusted in order to set `RESOLC_WASM_URI` from env variable - ⚠️ Release workflow is changed: - In PRs and main branch it'll only build artifacts - Release will happen automatically only on the `v*` tag push. This is needed for revive_web.js to have the necessary `RESOLC_WASM_URI` - workflow will check that version in Cargo.toml is the same as the tag when the new tag is pushed cc paritytech#162 cc paritytech/devops#3890
1 parent 7d8fa75 commit 0dafc77

File tree

6 files changed

+231
-34
lines changed

6 files changed

+231
-34
lines changed

.github/scripts/json_generator.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import os
2+
import sys
3+
import json
4+
import requests
5+
from datetime import datetime
6+
7+
def validate_github_token():
8+
"""Validate that GITHUB_TOKEN environment variable is set."""
9+
if 'GITHUB_TOKEN' not in os.environ:
10+
print("Error: GITHUB_TOKEN environment variable is not set.")
11+
sys.exit(1)
12+
13+
def fetch_release_data(repo, tag):
14+
"""Fetch release data from GitHub API."""
15+
url = f"https://api.github.com/repos/{repo}/releases/tags/{tag}"
16+
headers = {
17+
'Authorization': f"Bearer {os.environ['GITHUB_TOKEN']}",
18+
'Accept': 'application/vnd.github+json',
19+
'X-GitHub-Api-Version': '2022-11-28'
20+
}
21+
22+
try:
23+
response = requests.get(url, headers=headers)
24+
response.raise_for_status()
25+
return response.json()
26+
except requests.RequestException as e:
27+
print(f"Error fetching release data: {e}")
28+
sys.exit(1)
29+
30+
def extract_build_hash(target_commitish):
31+
"""Extract the first 8 characters of the commit hash."""
32+
return f"commit.{target_commitish[:8]}"
33+
34+
def generate_asset_json(release_data, asset):
35+
"""Generate JSON for a specific asset."""
36+
version = release_data['tag_name'].lstrip('v')
37+
build = extract_build_hash(release_data['target_commitish'])
38+
long_version = f"{version}+{build}"
39+
path = f"{asset['name']}+{long_version}"
40+
41+
return {
42+
"path": path,
43+
"name": asset['name'],
44+
"version": version,
45+
"build": build,
46+
"longVersion": long_version,
47+
"url": asset['browser_download_url'],
48+
"firstSolcVersion": os.environ["FIRST_SOLC_VERSION"],
49+
"lastSolcVersion": os.environ["LAST_SOLC_VERSION"]
50+
}
51+
52+
def save_platform_json(platform_folder, asset_json, tag):
53+
"""Save asset JSON and update list.json for a specific platform."""
54+
# Create platform folder if it doesn't exist
55+
os.makedirs(platform_folder, exist_ok=True)
56+
57+
# Update or create list.json
58+
list_file_path = os.path.join(platform_folder, "list.json")
59+
60+
if os.path.exists(list_file_path):
61+
with open(list_file_path, 'r') as f:
62+
try:
63+
list_data = json.load(f)
64+
except json.JSONDecodeError:
65+
list_data = {"builds": [], "releases": {}, "latestRelease": ""}
66+
else:
67+
list_data = {"builds": [], "releases": {}, "latestRelease": ""}
68+
69+
# Remove any existing entry with the same path
70+
list_data['builds'] = [
71+
build for build in list_data['builds']
72+
if build['path'] != asset_json['path']
73+
]
74+
# Add the new build
75+
list_data['builds'].append(asset_json)
76+
77+
# Update releases
78+
version = asset_json['version']
79+
list_data['releases'][version] = asset_json['path']
80+
81+
# Update latest release
82+
list_data['latestRelease'] = version
83+
84+
with open(list_file_path, 'w') as f:
85+
json.dump(list_data, f, indent=4)
86+
87+
def main():
88+
# Validate arguments
89+
if len(sys.argv) != 3:
90+
print("Usage: python script.py <repo> <tag>")
91+
sys.exit(1)
92+
93+
repo, tag = sys.argv[1], sys.argv[2]
94+
95+
# Validate GitHub token
96+
validate_github_token()
97+
98+
# Fetch release data
99+
release_data = fetch_release_data(repo, tag)
100+
101+
# Mapping of asset names to platform folders
102+
platform_mapping = {
103+
'resolc-x86_64-unknown-linux-musl': 'linux',
104+
'resolc-universal-apple-darwin': 'macos',
105+
'resolc-x86_64-pc-windows-msvc.exe': 'windows',
106+
'resolc_web.js': 'wasm'
107+
}
108+
109+
# Process each asset
110+
for asset in release_data['assets']:
111+
platform_name = platform_mapping.get(asset['name'])
112+
if platform_name:
113+
platform_folder = os.path.join(platform_name)
114+
asset_json = generate_asset_json(release_data, asset)
115+
save_platform_json(platform_folder, asset_json, tag)
116+
print(f"Processed {asset['name']} for {platform_name}")
117+
118+
if __name__ == "__main__":
119+
main()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Generate JSON for resolc-bin
2+
on:
3+
release:
4+
types: [published]
5+
6+
jobs:
7+
generateJson:
8+
runs-on: ubuntu-latest
9+
if: contains(github.event.release.tag_name, 'llvm') == false
10+
environment: tags
11+
env:
12+
# the token is needed for json_generator.py
13+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
with:
18+
path: tmp
19+
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
with:
23+
repository: paritytech/resolc-bin
24+
path: resolc-bin
25+
26+
- uses: actions/create-github-app-token@v1
27+
id: app-token
28+
with:
29+
app-id: ${{ secrets.REVIVE_JSON_APP_ID }}
30+
private-key: ${{ secrets.REVIVE_JSON_APP_KEY }}
31+
owner: paritytech
32+
repositories: resolc-bin
33+
34+
- name: Generate json and push
35+
env:
36+
TOKEN: ${{ steps.app-token.outputs.token }}
37+
APP_NAME: "paritytech-revive-json"
38+
Green: "\e[32m"
39+
NC: "\e[0m"
40+
run: |
41+
sudo apt-get update && sudo apt-get install -y wget
42+
wget https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/resolc-x86_64-unknown-linux-musl
43+
chmod +x resolc-x86_64-unknown-linux-musl
44+
export FIRST_SOLC_VERSION=$(./resolc-x86_64-unknown-linux-musl --supported-solc-versions | cut -f 1 -d "," | tr -d ">=")
45+
export LAST_SOLC_VERSION=$(./resolc-x86_64-unknown-linux-musl --supported-solc-versions | cut -f 2 -d "," | tr -d "<=")
46+
47+
cd resolc-bin
48+
python ../tmp/.github/scripts/json_generator.py ${GITHUB_REPOSITORY} ${{ github.event.release.tag_name }}
49+
50+
echo "${Green}Add new remote with gh app token${NC}"
51+
git remote set-url origin $(git config remote.origin.url | sed "s/github.com/${APP_NAME}:${TOKEN}@github.com/g")
52+
53+
echo "${Green}Remove http section that causes issues with gh app auth token${NC}"
54+
sed -i.bak '/\[http/d' ./.git/config
55+
sed -i.bak '/extraheader/d' ./.git/config
56+
57+
git config user.email "[email protected]"
58+
git config user.name "${APP_NAME}"
59+
60+
git add .
61+
git commit -m "Update json"
62+
git push origin main
63+
64+
echo "::notice::info.list files were successfully published to https://github.com/paritytech/resolc-bin"

.github/workflows/release.yml

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
name: Release
1+
name: Build & Release
22
on:
33
push:
44
branches: ["main"]
5+
tags:
6+
- "v*"
57
pull_request:
68
branches: ["main"]
79
types: [opened, synchronize, labeled, unlabeled]
8-
workflow_dispatch:
910

1011
concurrency:
1112
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
@@ -17,41 +18,44 @@ env:
1718

1819
jobs:
1920
check-version-changed:
20-
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'release-test')
2121
runs-on: ubuntu-24.04
2222
permissions:
2323
contents: write
24+
env:
25+
CURRENT_TAG: ${{ github.ref_name }}
2426
outputs:
25-
TAG: ${{ steps.versions.outputs.TAG }}
26-
PKG_VER: ${{ steps.versions.outputs.PKG_VER }}
2727
RELEASE_NOTES: ${{ steps.versions.outputs.RELEASE_NOTES }}
2828
steps:
2929
- uses: actions/checkout@v4
30-
with:
31-
fetch-tags: true
32-
fetch-depth: 0
3330

34-
- name: Check Versions
31+
# Check that tag and version in Cargo.toml match
32+
- name: Check versions
3533
id: versions
3634
run: |
37-
export CURRENT_TAG=$(git describe --tags --abbrev=0 --exclude "llvm-*")
35+
if [[ $CURRENT_TAG == 'main' ]];
36+
then
37+
echo "::notice::Tag $CURRENT_TAG is not a release tag, skipping the check in the main branch";
38+
exit 0
39+
fi
40+
41+
if [[ $CURRENT_TAG != "v"* ]];
42+
then
43+
echo "::notice::Tag $CURRENT_TAG is not a release tag, skipping the check in a PR";
44+
exit 0
45+
fi
46+
3847
export PKG_VER=v$(cat Cargo.toml | grep -A 5 package] | grep version | cut -d '=' -f 2 | tr -d '"' | tr -d " ")
3948
echo "Current tag $CURRENT_TAG"
4049
echo "Package version $PKG_VER"
4150
#
42-
echo "PKG_VER=$PKG_VER" >> $GITHUB_OUTPUT
43-
if [[ $CURRENT_TAG == $PKG_VER ]];
51+
if [[ $CURRENT_TAG != $PKG_VER ]];
4452
then
45-
echo "Tag is up to date. Nothing to do.";
46-
export TAG=old;
47-
else
48-
echo "Tag was updated.";
49-
export TAG=new;
53+
echo "::error::Tag $CURRENT_TAG doesn't match package version $PKG_VER in Cargo.toml, please fix";
54+
exit 1
5055
fi
51-
echo "TAG=$TAG" >> $GITHUB_OUTPUT
5256
5357
# Generating release notes early, in order to avoid checkout at the last step
54-
export RELEASE_NOTES="$(sed '/^## '${PKG_VER}'/,/^## v/!d' CHANGELOG.md | sed -e '1d' -e '$d')"
58+
export RELEASE_NOTES="$(sed '/^## '${CURRENT_TAG}'/,/^## v/!d' CHANGELOG.md | sed -e '1d' -e '$d')"
5559
5660
echo "Release notes:"
5761
echo "$RELEASE_NOTES"
@@ -83,7 +87,6 @@ jobs:
8387
- target: x86_64-pc-windows-msvc
8488
type: native
8589
runner: windows-2022
86-
if: ${{ needs.check-version-changed.outputs.TAG == 'new' }}
8790
runs-on: ${{ matrix.runner }}
8891
needs: [check-version-changed]
8992
steps:
@@ -137,9 +140,10 @@ jobs:
137140
retention-days: 1
138141

139142
build-wasm:
140-
if: ${{ needs.check-version-changed.outputs.TAG == 'new' }}
141143
runs-on: ubuntu-24.04
142144
needs: [check-version-changed]
145+
env:
146+
RELEASE_RESOLC_WASM_URI: https://github.com/paritytech/revive-workflow-test/releases/download/${{ github.ref_name }}/resolc.wasm
143147
steps:
144148
- uses: actions/checkout@v4
145149
- uses: actions-rust-lang/setup-rust-toolchain@v1
@@ -226,11 +230,10 @@ jobs:
226230
retention-days: 1
227231

228232
create-release:
229-
if: github.event_name != 'pull_request'
233+
if: startsWith(github.ref_name, 'v')
230234
needs: [check-version-changed, build-wasm]
231235
runs-on: macos-14
232-
permissions:
233-
contents: write
236+
environment: tags
234237
steps:
235238
- name: Download Artifacts
236239
uses: actions/download-artifact@v4
@@ -246,6 +249,12 @@ jobs:
246249
chmod +x resolc-x86_64-unknown-linux-musl
247250
chmod +x resolc-universal-apple-darwin
248251
252+
- uses: actions/create-github-app-token@v1
253+
id: app-token
254+
with:
255+
app-id: ${{ secrets.REVIVE_RELEASE_APP_ID }}
256+
private-key: ${{ secrets.REVIVE_RELEASE_APP_KEY }}
257+
249258
- name: create-release
250259
uses: softprops/action-gh-release@v2
251260
with:
@@ -255,9 +264,10 @@ jobs:
255264
256265
## Note for macOS Users
257266
The macOS binary is unsigned and it needs to be made runnable using `xattr -c resolc-universal-apple-darwin`.
258-
tag_name: ${{ needs.check-version-changed.outputs.PKG_VER }}
259-
name: ${{ needs.check-version-changed.outputs.PKG_VER }}
260-
draft: true
267+
tag_name: ${{ github.ref_name }}
268+
name: ${{ github.ref_name }}
269+
prerelease: true
270+
token: ${{ steps.app-token.outputs.token }}
261271
target_commitish: ${{ github.sha }}
262272
files: |
263273
resolc-x86_64-unknown-linux-musl

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
install: install-bin install-npm
2424

2525
install-bin:
26-
cargo install --path crates/solidity
26+
cargo install --locked --path crates/solidity
2727

2828
install-npm:
2929
npm install && npm fund

RELEASE.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@ Prior to the first stable release we neither have formal release processes nor d
44

55
To create a new pre-release:
66

7-
1. Create a release PR which updates the `-dev.X` versions in the workspace `Cargo.toml` and updates the `CHANGELOG.md` accordingly. Add the `release-test` label to trigger the release workflows.
8-
2. If the CI passes, merge the release PR. The release workflow will attempt to build and publish a new release whenever the latest git tag does not match the cargo package version.
9-
3. Wait for the `Release` workflow to finish. If the workflow fails after the `build-linux-all` step, check if a tag has been created and delete it before restarting or pushing updates. Note: It's more convenient to debug the release workflow in a fork (the fork has to be under the `paritytech` org to access `parity-large` runners).
10-
4. Check draft release on [Releases page](https://github.com/paritytech/revive/releases) and publish (should contain `resolc.js`, `resolc.wasm`, `resolc-web.js`, and `resolc-static-linux` release assets)
11-
5. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
7+
1. Create a release PR which updates the `-dev.X` versions in the workspace `Cargo.toml` and updates the `CHANGELOG.md` accordingly.
8+
2. If the CI passes, merge the release PR.
9+
3. Push a tag that has the same `-dev.X` version as in `Cargo.toml`
10+
4. The release workflow will attempt to build and publish a new pre-release if the latest tag does match the cargo package version.
11+
5. Wait for the `Release` workflow to finish. It should create the pre-release with the same `-dev.X` name.
12+
6. Check that pre-release was created on the [Releases page](https://github.com/paritytech/revive/releases) with all artifacts.
13+
7. After the release is published, another workflow should start automatically and update json files in https://github.com/paritytech/resolc-bin. Check the changes.
14+
8. Update the [contract-docs](https://github.com/paritytech/contract-docs/) accordingly
1215

1316
# LLVM release
1417

js/build.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ const { minify } = require("terser");
44

55
const SOLJSON_URI =
66
"https://binaries.soliditylang.org/wasm/soljson-v0.8.29+commit.ab55807c.js";
7-
const RESOLC_WASM_URI = "http://127.0.0.1:8080/resolc.wasm";
7+
const RESOLC_WASM_URI =
8+
process.env.RELEASE_RESOLC_WASM_URI || "http://127.0.0.1:8080/resolc.wasm";
89
const RESOLC_WASM_TARGET_DIR = path.join(
910
__dirname,
1011
"../target/wasm32-unknown-emscripten/release",

0 commit comments

Comments
 (0)