Skip to content

Commit b530ffb

Browse files
author
Tarik Eshaq
authored
Create PR when Application Services makes a release (#8)
* Adds automation and github actions
1 parent de4b054 commit b530ffb

File tree

6 files changed

+234
-1
lines changed

6 files changed

+234
-1
lines changed

.github/workflows/update-as.yml

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
name: Create a PR for release with the newest A-S version available
2+
3+
# Controls when the workflow will run
4+
on:
5+
schedule:
6+
# Runs every minute of the 3pm UTC hour of each day
7+
- cron: '* 15 * * *'
8+
9+
jobs:
10+
release-pr:
11+
runs-on: macos-latest
12+
strategy:
13+
max-parallel: 1
14+
matrix:
15+
python-version: [3.7]
16+
env:
17+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18+
steps:
19+
# Checks out the rust-components-swift repository
20+
- uses: actions/checkout@v2
21+
with:
22+
token: ${{ secrets.GITHUB_TOKEN }}
23+
submodules: 'recursive'
24+
- name: Setup Python ${{ matrix.python-version }}
25+
uses: actions/setup-python@v1
26+
with:
27+
python-version: ${{ matrix.python-version }}
28+
- name: Install Python dependencies
29+
run: |
30+
python -m pip install --upgrade pip
31+
pip install -r ./automation/requirements.txt
32+
# Gets the new application services tag, and stores it in
33+
# the environment variable `AS_VERSION` to be used later
34+
- name: Get new A-S tag
35+
run: |
36+
echo "AS_VERSION=`python automation/read_as_tag.py`" >> $GITHUB_ENV
37+
# Check if a branch was already created on github
38+
# and set an environment variable `ALREADY_CREATED` to
39+
# prevent us from creating multiple PRs/branches
40+
- name: Check if job already ran with this release
41+
run: |
42+
echo "ALREADY_CREATED=$(python automation/is_already_updated.py)" >> $GITHUB_ENV
43+
- name: Setup git information
44+
if: env.ALREADY_CREATED == 'false'
45+
run: |
46+
git config user.email "[email protected]"
47+
git config user.name "Firefox Sync Engineering"
48+
git checkout -b update-as-to-${{ env.AS_VERSION }}
49+
50+
# Update the submodule if we haven't ran those jobs yet
51+
# note that we commit here
52+
- name: Update the submodule to the release application services
53+
if: env.ALREADY_CREATED == 'false'
54+
run: |
55+
cd external/application-services
56+
git fetch --all --tags
57+
git checkout $AS_VERSION
58+
cd ../..
59+
git commit -am "Updates application services submodule to $AS_VERSION"
60+
- name: Update Package.swift with new xcframework URL and checksum
61+
if: env.ALREADY_CREATED == 'false'
62+
run: |
63+
python automation/update_package_swift.py
64+
git commit -am "Updates Package.swift with $AS_VERSION release"
65+
66+
- name: Install Rust for the make_tag script
67+
if: env.ALREADY_CREATED == 'false'
68+
run: |
69+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
70+
source $HOME/.cargo/env
71+
- name: Install swiftformat to format the uniffi generated bindings
72+
if: env.ALREADY_CREATED == 'false'
73+
run: |
74+
brew install swiftformat
75+
# We strip away the `v` in the AS Version and run the make_tag
76+
# script, which will generate all the code that needs to be generated
77+
# Note that the tag argument isn't useful here, since we will
78+
# have to cut a release with a new tag (possibly with the same name)
79+
# after the PR is merged
80+
- name: Runs make_tag script
81+
if: env.ALREADY_CREATED == 'false'
82+
run: |
83+
./make_tag.sh ${AS_VERSION:1}
84+
- name: Create Pull Request
85+
if: env.ALREADY_CREATED == 'false'
86+
run: |
87+
git push origin update-as-to-${{ env.AS_VERSION }} -f
88+
gh pr create --title "Auto update with latest AS Release ${{ env.AS_VERSION}}" --body "Updates the swift package with the latest Application Services Release" --base "main"
89+

Package.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ let package = Package(
3939
name: "MozillaRustComponents",
4040
//
4141
// For release artifacts, reference the MozillaRustComponents as a URL with checksum.
42-
//
42+
// IMPORTANT: The checksum has to be on the line directly after the `url`
43+
// this is important for our release script so that all values are updated correctly
4344
url: "https://117909-129966583-gh.circle-artifacts.com/0/dist/MozillaRustComponents.xcframework.zip",
4445
checksum: "92a66ee992a3848dae8319be996833120e9a86f2bc08354d181b81197bf79e4e"
4546

automation/is_already_updated.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import os
2+
from github import Github
3+
4+
GITHUB_REPO = "mozilla/rust-components-swift"
5+
XC_FRAMEWORK_NAME = "MozillaRustComponents.xcframework.zip"
6+
github_access_token = os.getenv("GITHUB_TOKEN")
7+
as_version = os.getenv("AS_VERSION")
8+
PACKAGE_SWIFT = "Package.swift"
9+
10+
def is_already_at_version():
11+
with open(PACKAGE_SWIFT) as fp:
12+
line = fp.readline()
13+
while line:
14+
line = fp.readline()
15+
16+
# If this is the line that has the URL to
17+
# the xcframework
18+
if XC_FRAMEWORK_NAME in line:
19+
return as_version in line
20+
return False
21+
22+
def is_branch_created():
23+
g = Github(github_access_token)
24+
repo = g.get_repo(GITHUB_REPO)
25+
26+
for branch in repo.get_branches():
27+
if f"update-as-to-{as_version}" in branch.name:
28+
return True
29+
return False
30+
31+
def main():
32+
'''
33+
Prints to stdout if rust-components-swift has already
34+
been updated to latest application services or
35+
if a PR has already been created
36+
'''
37+
if not github_access_token or not as_version:
38+
exit(1)
39+
if is_already_at_version() or is_branch_created():
40+
print("true")
41+
else:
42+
print("false")
43+
44+
if __name__ == '__main__':
45+
main()

automation/read_as_tag.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import os
2+
from github import Github
3+
4+
GITHUB_REPO = "mozilla/application-services"
5+
github_access_token = os.getenv("GITHUB_TOKEN")
6+
7+
def get_latest_as_version():
8+
g = Github(github_access_token)
9+
repo = g.get_repo(GITHUB_REPO)
10+
11+
latest_release = repo.get_releases()[0]
12+
return (str(latest_release.tag_name))
13+
14+
def main():
15+
'''
16+
Gets the latest application services
17+
version and prints it to stdout
18+
'''
19+
if not github_access_token:
20+
exit(1)
21+
as_repo_tag = get_latest_as_version()
22+
print(as_repo_tag)
23+
24+
if __name__ == '__main__':
25+
main()

automation/requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
requests
2+
pygithub

automation/update_package_swift.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import os
2+
from github import Github
3+
import hashlib
4+
import requests
5+
6+
GITHUB_REPO = "mozilla/application-services"
7+
XC_FRAMEWORK_NAME = "MozillaRustComponents.xcframework.zip"
8+
PACKAGE_SWIFT = "Package.swift"
9+
github_access_token = os.getenv("GITHUB_TOKEN")
10+
as_version = os.getenv("AS_VERSION")
11+
12+
def get_xcframework_artifact():
13+
g = Github(github_access_token)
14+
repo = g.get_repo(GITHUB_REPO)
15+
16+
release = repo.get_release(as_version)
17+
for asset in release.get_assets():
18+
if asset.name == XC_FRAMEWORK_NAME:
19+
return asset.browser_download_url
20+
21+
def compute_checksum(xc_framework_url):
22+
req = requests.get(xc_framework_url)
23+
return hashlib.sha256(req.content).hexdigest()
24+
25+
def update_package_swift(xc_framework_url, checksum):
26+
old_url = ''
27+
old_checksum = ''
28+
with open(PACKAGE_SWIFT) as fp:
29+
line = fp.readline()
30+
while line:
31+
line = fp.readline()
32+
33+
# If this is the line that has the URL to
34+
# the xcframework
35+
if XC_FRAMEWORK_NAME in line:
36+
url_start = line.find('"') + 1
37+
url_end = line.find('"', url_start)
38+
old_url = line[url_start:url_end]
39+
# NOTE: We assume that the next line is the
40+
# checksum, there is a note in Package.swift
41+
# to make sure we don't change that
42+
line = fp.readline()
43+
checksum_start = line.find('"') + 1
44+
checksum_end = line.find('"', checksum_start)
45+
old_checksum = line[checksum_start:checksum_end]
46+
break
47+
file = open(PACKAGE_SWIFT, "r+")
48+
data = file.read()
49+
data = data.replace(old_url, xc_framework_url)
50+
data = data.replace(old_checksum, checksum)
51+
file.close()
52+
file = open(PACKAGE_SWIFT, "wt")
53+
file.write(data)
54+
file.close()
55+
56+
57+
def main():
58+
'''
59+
Updates `Package.swift` with the latest
60+
xcframework
61+
'''
62+
if not github_access_token or not as_version:
63+
exit(1)
64+
xc_framework_url = get_xcframework_artifact()
65+
checksum = compute_checksum(xc_framework_url)
66+
update_package_swift(xc_framework_url, checksum)
67+
68+
69+
70+
if __name__ == '__main__':
71+
main()

0 commit comments

Comments
 (0)