Skip to content

Commit

Permalink
chore: Adding automatic homebrew formula generation (#20)
Browse files Browse the repository at this point in the history
## Describe your changes

* Adding functionality to Github action to generate an updated homebrew
formula when a merge to main occurs and creates a pull request in the
homebrew-formula repository

Link to automated formula creation -
https://github.com/slalombuild/homebrew-secureli/pull/7/files
## Issue ticket number and link

* https://slalom.atlassian.net/browse/STFT-136

## Checklist before requesting a review
- [*] I have performed a self-review of my code

---------

Co-authored-by: Raul Centeno <[email protected]>
  • Loading branch information
centenor and Raul Centeno authored Apr 5, 2023
1 parent ba2de19 commit ef767f2
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 36 deletions.
52 changes: 40 additions & 12 deletions .github/workflows/secureliCI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ jobs:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Checkout Secureli Homebrew Repo
uses: actions/checkout@v3
with:
repository: slalombuild/homebrew-secureli
token: ${{ secrets.ADMIN_TOKEN_SASCHA }} # `GH_PAT` is a secret that contains your PAT
path: homebrew-secureli
- name: Validate Branch name
run: ./scripts/get-current-branch.sh
- name: Set up Python 3.9
Expand All @@ -40,7 +46,7 @@ jobs:
git config user.name github-actions
git config user.email [email protected]
semantic-release publish
# A NOOP run on feature branches
# A NOOP run on feature branches
- name: Verify Semantic Release
if: github.ref != 'refs/heads/main'
run: |
Expand All @@ -49,14 +55,36 @@ jobs:
git config user.name github-actions
git config user.email [email protected]
semantic-release publish --noop
# - name: Verify SemVer Release
# if: github.ref != 'refs/heads/main'
# uses: relekang/python-semantic-release@master
# with:
# github_token: ${{ secrets.ADMIN_TOKEN_SASCHA }}
# additional_options: --noop
# - name: SemVer Version Release
# if: github.ref == 'refs/heads/main'
# uses: relekang/python-semantic-release@master
# with:
# github_token: ${{ secrets.ADMIN_TOKEN_SASCHA }}
deploy:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Checkout Secureli Homebrew Repo
uses: actions/checkout@v3
with:
repository: slalombuild/homebrew-secureli
token: ${{ secrets.ADMIN_TOKEN_SASCHA }} # `GH_PAT` is a secret that contains your PAT
path: homebrew-secureli
- name: Homebrew Formula Generation
env:
GH_TOKEN: ${{ secrets.ADMIN_TOKEN_SASCHA }}
run: |
pip install requests jinja2 poetry
poetry build
poetry install
export secureliVersion=$(poetry version | awk '{print $2}')
export secureliSha256=$(sha256sum dist/secureli-${secureliVersion}.tar.gz | awk '{print $1}')
git config --global user.email "[email protected]"
git config --global user.name "Secureli Automation"
python ./scripts/get-secureli-dependencies.py
cd homebrew-secureli
git checkout -b "secureli-${secureliVersion}-formula-generation"
git add ./Formula/secureli.rb
git commit -m "Creating pull request with latest Secureli formula for version ${secureliVersion}"
git push origin secureli-${secureliVersion}-formula-generation --repo https://github.com/slalombuild/homebrew-secureli.git
gh pr create --title "Secureli Formula Automated Creation for version ${secureliVersion}" --body "Automated formula creation"
21 changes: 0 additions & 21 deletions bitbucket-pipelines.yml

This file was deleted.

6 changes: 3 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ typer = {version = "^0.6.1", extras = ["all"]}
pygments = "^2.13.0"
dependency-injector = {version = "^4.40.0", extras = ["yaml"]}
pydantic = "^1.10.2"
pre-commit = "^2.20.0"
jinja2 = "^3.1.2"

[tool.pytest.ini_options]
Expand All @@ -37,6 +36,7 @@ black = "^22.10.0"
identify = "^2.5.7"
poethepoet = "^0.16.4"
python-semantic-release = "^7.33.1"
pre-commit = "^2.20.0"

[build-system]
requires = ["poetry-core"]
Expand All @@ -49,10 +49,10 @@ version_toml = [
major_on_zero = true
branch = "main"
upload_to_PyPI = false
upload_to_release = false
upload_to_release = true
upload_to_repository = false
prerelease = true
parser_angular_default_level_bump = "patch"
parser_angular_patch_types = "fix,perf,docs,chore"
build_command = false
build_command = "poetry build"
# 'pip install pre-commit && pip install poetry && poetry build'
77 changes: 77 additions & 0 deletions scripts/get-secureli-dependencies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import requests
import subprocess
import os
from jinja2 import Environment, FileSystemLoader

# Set necessary top level vars
environment = Environment(loader=FileSystemLoader("templates/"), autoescape=True)
template = environment.get_template("formula.txt")
filename = "secureli.rb"
secureliVersion = os.getenv("secureliVersion")
secureliSha256 = os.getenv("secureliSha256")
secureliPackageUrl = f"https://github.com/slalombuild/homebrew-secureli/releases/download/v{secureliVersion}/secureli-{secureliVersion}.tar.gz"
secureliPackageDependencies = []
secureliFormulaPath = "./homebrew-secureli/Formula"

secureliPackageNamesCmd = "poetry show --only main | awk '{print $1}'"
secureliPackageVersionsCmd = "poetry show --only main | awk '{print $2}'"

getPackageNames = subprocess.Popen(
["poetry", "show", "--only", "main"], stdout=subprocess.PIPE
)
filterPackageNames = subprocess.Popen(
["awk", "{print $1}"], stdin=getPackageNames.stdout, stdout=subprocess.PIPE
)
getPackageNames.stdout.close()

secureliPackageNames, error = filterPackageNames.communicate()

decodedSecureliPackageNames = secureliPackageNames.decode("utf-8").split()

getPackageVersions = subprocess.Popen(
["poetry", "show", "--only", "main"], stdout=subprocess.PIPE
)
filterPackageVersions = subprocess.Popen(
["awk", "{print $2}"], stdin=getPackageVersions.stdout, stdout=subprocess.PIPE
)
getPackageVersions.stdout.close()

secureliPackageVersions, error = filterPackageVersions.communicate()

decodedSecureliPackageVersions = secureliPackageVersions.decode("utf-8").split()

# This loops through all packages that secureli requires to be properly built
# It then outputs the package information to a dictionary that will be templated into a Homebrew formula for end-user consumption
for packageName, packageVersion in zip(
decodedSecureliPackageNames, decodedSecureliPackageVersions
):
print(
f"The necessary package retrieved from poetry is {packageName} with version {packageVersion}"
)
packagePayload = requests.get(
f"https://pypi.org/pypi/{packageName}/{packageVersion}/json"
)
packagePayloadJsonDict = packagePayload.json()

for package in packagePayloadJsonDict["urls"]:
if package["packagetype"] == "sdist":
url = package["url"]
sha256 = package["digests"]["sha256"]
break

# Load all the retrieved package info from pypi into a dictionary
data = {"packageName": packageName, "packageUrl": url, "sha256": sha256}
secureliPackageDependencies.append(data)

# Create a dict that contains all the package dependency information
# Context will then be passed into the Jinja template renderer to create the homebrew file
context = {
"secureliPackageDependencies": secureliPackageDependencies,
"secureliVersion": secureliVersion,
"secureliSha256": secureliSha256,
"secureliPackageUrl": secureliPackageUrl,
}

with open(f"{secureliFormulaPath}/{filename}", mode="w", encoding="utf-8") as message:
message.write(template.render(context))
print(f"Homebrew formula file called {filename} has been created")
29 changes: 29 additions & 0 deletions templates/formula.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require_relative "lib/custom_download_strategy"

class Secureli < Formula
include Language::Python::Virtualenv
desc "SeCureLI is a tool that enables you to experience the delight of building products by helping you get ideas from your head into working software as frictionlessly as possible, in a reliable, secure, scalable, and observable way"
homepage "https://github.com/slalombuild/secureli"
url "{{ secureliPackageUrl }}", :using => GitHubPrivateRepositoryReleaseDownloadStrategy
version "{{ secureliVersion }}"
sha256 "{{ secureliSha256 }}"

depends_on "pre-commit"

depends_on "[email protected]"

{% for package in secureliPackageDependencies %}
resource "{{ package.packageName }}" do
url "{{ package.packageUrl}}"
sha256 "{{ package.sha256 }}"
end
{% endfor %}

def install
virtualenv_install_with_resources
end

test do
system "secureli", "--help"
end
end

0 comments on commit ef767f2

Please sign in to comment.