Skip to content

Commit

Permalink
ci: automate hombrew releases (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
yurijmikhalevich authored Aug 20, 2023
1 parent 9798f97 commit c8112f4
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 4 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,40 @@ jobs:
- run: poetry build
- uses: pypa/gh-action-pypi-publish@release/v1

brew:
runs-on: ubuntu-22.04
# the Formula references the rclip package published to PyPI
needs: pypi
steps:
- name: Parse the Version
id: version
run: |
echo ::set-output name=PRERELEASE::$(
[[ ! $GITHUB_REF =~ ^refs\/tags\/v[0-9]+\.[0-9]+\.[0-9]+$ ]] && echo "true"
)
- uses: actions/checkout@v3
if: ${{ steps.version.outputs.PRERELEASE != 'true' }}
- uses: actions/setup-python@v4
if: ${{ steps.version.outputs.PRERELEASE != 'true' }}
with:
python-version: 3.8
- name: Install dependencies
if: ${{ steps.version.outputs.PRERELEASE != 'true' }}
run: |
python -m pip install --upgrade pip
pip install --upgrade poetry
poetry install
- name: Setup git
if: ${{ steps.version.outputs.PRERELEASE != 'true' }}
run: |
git config --global user.email "[email protected]"
git config --global user.name "Zhi Bot"
- name: Release
if: ${{ steps.version.outputs.PRERELEASE != 'true' }}
env:
GITHUB_TOKEN: ${{ secrets.ZHIBOT_GITHUB_TOKEN }}
run: make release-brew

snap:
runs-on: ubuntu-20.04
steps:
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ test:
build-docker:
DOCKER_DEFAULT_PLATFORM=linux/amd64 docker build . -t rclip

# CI runs release-brew as part of the `release` action
release-brew:
poetry run ./release-utils/homebrew/release.sh

release:
@test $(VERSION) || (echo "VERSION arg is required" && exit 1)
poetry version $(VERSION)
Expand Down
33 changes: 32 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "rclip"
version = "1.5.0a0"
version = "1.5.0a7"
description = "AI-Powered Command-Line Photo Search Tool"
authors = ["Yurij Mikhalevich <[email protected]>"]
license = "MIT"
Expand Down Expand Up @@ -35,6 +35,8 @@ tqdm = "^4.65.0"
[tool.poetry.group.dev.dependencies]
pycodestyle = ">=2.7,<3.0"
pytest = ">=7.2.1,<8.0"
homebrew-pypi-poet = "^0.10.0"
jinja2 = "^3.1.2"

[tool.poetry.scripts]
rclip = "rclip.main:main"
Expand Down
81 changes: 81 additions & 0 deletions release-utils/homebrew/generate_formula.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import hashlib
import jinja2
import poet
import requests

env = jinja2.Environment(trim_blocks=True)


TEMPLATE = env.from_string('''class Rclip < Formula
include Language::Python::Virtualenv
desc "AI-Powered Command-Line Photo Search Tool"
homepage "https://github.com/yurijmikhalevich/rclip"
url "{{ package.url }}"
sha256 "{{ package.checksum }}"
license "MIT"
depends_on "rust" => :build # for safetensors
depends_on "numpy"
depends_on "pillow"
depends_on "python-certifi"
depends_on "[email protected]"
depends_on "pytorch"
depends_on "sentencepiece"
depends_on "torchvision"
{{ resources }}
def install
virtualenv_install_with_resources
# link dependent virtualenvs to this one
site_packages = Language::Python.site_packages("python3.11")
paths = %w[pytorch torchvision].map do |package_name|
package = Formula[package_name].opt_libexec
package/site_packages
end
(libexec/site_packages/"homebrew-deps.pth").write paths.join("\\n")
end
test do
output = shell_output("#{bin}/rclip cat")
assert_match("score\\tfilepath", output)
end
end
''')


# These deps are being installed from brew
DEPS_TO_IGNORE = ['numpy', 'pillow', 'certifi', 'torch', 'torchvision']
RESOURCE_URL_OVERRIDES = {
# open-clip-torch publishes an incomplete tarball to pypi, so we will fetch one from GitHub
'open-clip-torch': env.from_string(
'https://github.com/mlfoundations/open_clip/archive/refs/tags/v{{ version }}.tar.gz'
),
}


def main():
deps = poet.make_graph('rclip')
for dep in DEPS_TO_IGNORE:
deps.pop(dep, None)
for dep, url in RESOURCE_URL_OVERRIDES.items():
new_url = url.render(version=deps[dep]['version'])
deps[dep]['url'] = new_url
deps[dep]['checksum'] = compute_checksum(new_url)
for _, dep in deps.items():
dep["name"] = dep["name"].lower()

rclip_metadata = deps.pop('rclip')
resources = '\n\n'.join([poet.RESOURCE_TEMPLATE.render(resource=dep) for dep in deps.values()])
print(TEMPLATE.render(package=rclip_metadata, resources=resources))


def compute_checksum(url: str):
response = requests.get(url)
return hashlib.sha256(response.content).hexdigest()


if __name__ == '__main__':
main()
51 changes: 51 additions & 0 deletions release-utils/homebrew/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/bash
set -e

# the script requires gh cli and git to be installed and configured
# and push permissions to https://github.com/yurijmikhalevich/homebrew-tap

ORIG_PWD=$(pwd)
VERSION=$(poetry version -s)

TMP_DIR=$(mktemp -d -t release-rclip-brew-XXXXXXXXXX)
cd $TMP_DIR
echo "Working in $TMP_DIR"

function handle_exit() {
cd "$ORIG_PWD"
rm -rf $TMP_DIR
echo "Removed $TMP_DIR"
}
trap handle_exit 0 SIGHUP SIGINT SIGQUIT SIGABRT SIGTERM

if [[ "$GITHUB_ACTIONS" ]]; then
git clone "https://$GITHUB_TOKEN@github.com/yurijmikhalevich/homebrew-tap.git" homebrew-tap
else
git clone [email protected]:yurijmikhalevich/homebrew-tap.git homebrew-tap
fi
cd homebrew-tap

PR_BRANCH="rclip-$VERSION"
PR_TITLE="rclip $VERSION"

git checkout -b "$PR_BRANCH"
python "$ORIG_PWD/release-utils/homebrew/generate_formula.py" > Formula/rclip.rb
git commit -am "$PR_TITLE"
git push origin "$PR_BRANCH"
gh pr create --title "$PR_TITLE" --body "Automated commit updating **rclip** formula to $VERSION" --base main --head "$PR_BRANCH"
# it takes a few seconds for GHA to start checks on the PR
sleep 20
gh pr checks "$PR_BRANCH" --watch --fail-fast
gh pr edit "$PR_BRANCH" --add-label pr-pull
# it takes a few seconds for GHA to start checks on the PR
sleep 20
gh pr checks "$PR_BRANCH" --watch --fail-fast

# assert that PR_STATE was closed as it should
PR_STATE=$(gh pr view "$PR_BRANCH" --json state -q .state)
if [ "$PR_STATE" != "CLOSED" ]; then
echo "PR \"$PR_TITLE\" is not closed"
exit 1
fi

echo "Released rclip $VERSION"
4 changes: 2 additions & 2 deletions snap/snapcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ description: |
For a detailed demonstration, watch the video: https://www.youtube.com/watch?v=tAJHXOkHidw.
You can use another image as a query by passing a file path or even an URL to the image file to **rclip** and combine multiple queries. Check out the project's README on GitHub for more usage examples: https://github.com/yurijmikhalevich/rclip#readme.
version: 1.5.0a0
version: 1.5.0a7
website: https://github.com/yurijmikhalevich/rclip
contact: [email protected]
passthrough:
Expand All @@ -33,7 +33,7 @@ apps:
parts:
rclip:
plugin: python
source: ./snap/local/rclip-1.5.0a0.tar.gz
source: ./snap/local/rclip-1.5.0a7.tar.gz
build-packages:
- python3-pip
build-environment:
Expand Down

0 comments on commit c8112f4

Please sign in to comment.