diff --git a/.github/workflows/secureliCI.yml b/.github/workflows/secureliCI.yml index 8323afb7..98582992 100644 --- a/.github/workflows/secureliCI.yml +++ b/.github/workflows/secureliCI.yml @@ -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 @@ -40,7 +46,7 @@ jobs: git config user.name github-actions git config user.email github-actions@github.com 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: | @@ -49,14 +55,36 @@ jobs: git config user.name github-actions git config user.email github-actions@github.com 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 "secureli-automation@slalom.com" + 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" diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml deleted file mode 100644 index 000b97e9..00000000 --- a/bitbucket-pipelines.yml +++ /dev/null @@ -1,21 +0,0 @@ -image: python:3.9 -pipelines: - default: - - step: - name: Validate Branch - script: - - branch=$(bash ./scripts/get-current-branch.sh) - - step: - name: Scan - script: - - pipe: atlassian/git-secrets-scan:0.6.1 - - step: - name: Test - caches: - - pip - script: - - pip install poetry - - poetry install - - poetry run poe precommit - - poetry run poe coverage - - poetry run secureli yeti diff --git a/pyproject.toml b/pyproject.toml index 934541ad..f2e47eed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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] @@ -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"] @@ -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' diff --git a/scripts/get-secureli-dependencies.py b/scripts/get-secureli-dependencies.py new file mode 100644 index 00000000..390bf411 --- /dev/null +++ b/scripts/get-secureli-dependencies.py @@ -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") diff --git a/templates/formula.txt b/templates/formula.txt new file mode 100644 index 00000000..f022d10b --- /dev/null +++ b/templates/formula.txt @@ -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 "python@3.9" + + {% 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