From e72c823285bb4ff1b4c421cd08d5f2042fe1100e Mon Sep 17 00:00:00 2001 From: Jerry Marino Date: Thu, 1 Oct 2020 16:34:50 -0700 Subject: [PATCH] Binary release creation workflows (#262) * Binary release creation workflows This PR adds the ability to upload release artifact via XCHammer's github CI and it creates a release when pushing a tag to v* The github actions API doesn't play well with per commit artifacts. For now we create a release when pushing a tag. Consuming the per commit artifacts w/o the github actions API is blocked by this: https://github.com/actions/upload-artifact/issues/50 --- .github/workflows/ci.yml | 36 +++++++ .github/workflows/ci_push.yml | 36 +++++++ .github/workflows/upload_release_artifact.yml | 55 +++++++++++ Makefile | 6 +- README.md | 93 +++++++++++++------ 5 files changed, 194 insertions(+), 32 deletions(-) create mode 100644 .github/workflows/upload_release_artifact.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 039aeac6..eda805e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -150,3 +150,39 @@ jobs: - name: workspace_v2 run: make workspace_v2 + # This uploads `xchammer.zip` as an artifact to github actions + # For issues mentioned here + # https://github.com/actions/upload-artifact/issues/50 + # The Github URL can't be used with Bazel directly in an `http_archive` + # At the time of writing the only way to consume it is to: + # - get the release URL with the github actions API which is valid for 1 minute + # - pull the zip from that URL and re-host it: or somehow use it locally. + # - it'd probably be possible to impalement as a github actions repository + # and that's a lot of unwarranted complexity to integrate XCHammer. + # + # See README.md of how to use the artifact with Bazel + make_release: + name: make_release + runs-on: macOS-latest + steps: + - uses: actions/checkout@v2 + - name: bazel_cache_release + uses: actions/cache@v2 + env: + cache-name: bazel-cache-release + with: + path: ~/Library/Caches/Bazel + key: ${{ runner.os }}-build-${{ env.cache-name }} + restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}- + + - name: make_release + run: | + make release + # Set the BAZEL_BIN env var to the realpath + # Note: actions/upload-artifact@v2 at time of writing is falling + # apart when we give it a symlink base path + echo ::set-env name=BAZEL_BIN::$(readlink bazel-bin) + - uses: actions/upload-artifact@v2 + with: + name: xchammer + path: ${{ env.BAZEL_BIN }}/xchammer_dist_repo.zip diff --git a/.github/workflows/ci_push.yml b/.github/workflows/ci_push.yml index 7ed0647d..61bb2931 100644 --- a/.github/workflows/ci_push.yml +++ b/.github/workflows/ci_push.yml @@ -155,3 +155,39 @@ jobs: - name: workspace_v2 run: make workspace_v2 + # This uploads `xchammer.zip` as an artifact to github actions + # For issues mentioned here + # https://github.com/actions/upload-artifact/issues/50 + # The Github URL can't be used with Bazel directly in an `http_archive` + # At the time of writing the only way to consume it is to: + # - get the release URL with the github actions API which is valid for 1 minute + # - pull the zip from that URL and re-host it: or somehow use it locally. + # - it'd probably be possible to impalement as a github actions repository + # and that's a lot of unwarranted complexity to integrate XCHammer. + # + # See README.md of how to use the artifact with Bazel + make_release: + name: make_release + runs-on: macOS-latest + steps: + - uses: actions/checkout@v2 + - name: bazel_cache_release + uses: actions/cache@v2 + env: + cache-name: bazel-cache-release + with: + path: ~/Library/Caches/Bazel + key: ${{ runner.os }}-build-${{ env.cache-name }} + restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}- + + - name: make_release + run: | + make release + # Set the BAZEL_BIN env var to the realpath + # Note: actions/upload-artifact@v2 at time of writing is falling + # apart when we give it a symlink base path + echo ::set-env name=BAZEL_BIN::$(readlink bazel-bin) + - uses: actions/upload-artifact@v2 + with: + name: xchammer + path: ${{ env.BAZEL_BIN }}/xchammer_dist_repo.zip diff --git a/.github/workflows/upload_release_artifact.yml b/.github/workflows/upload_release_artifact.yml new file mode 100644 index 00000000..2cb53df1 --- /dev/null +++ b/.github/workflows/upload_release_artifact.yml @@ -0,0 +1,55 @@ +# This workflow cuts a per commit binary release of XCHammer and uploads +# the binary release WORKSPACE for later consumption. +# +# Basically push a tag to github for the commit and this will append the +# release artifact +# +# Ideally we'd create a Bazel consumeable artifact per commit but using github +# actions w/o any other systems it's not so possible +# https://github.com/actions/upload-artifact/issues/50 +on: + push: + tags: + - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10 + +name: Upload Release Artifact + +jobs: + build: + name: create_release + runs-on: macOS-latest + steps: + - uses: actions/checkout@v2 + - name: bazel_cache_release + uses: actions/cache@v2 + env: + cache-name: bazel-cache-release + with: + path: ~/Library/Caches/Bazel + key: ${{ runner.os }}-build-${{ env.cache-name }} + restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}- + + - name: make_release + run: make release + - name: create_release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + draft: false + prerelease: false + - name: upload_release_asset + id: upload-release-asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps + asset_path: bazel-bin/xchammer_dist_repo.zip + asset_name: xchammer.zip + asset_content_type: application/zip + + diff --git a/Makefile b/Makefile index 8fa7d295..ed7ff13e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY : test workspace archive install compile_commands debug run run_force test build build build-release +.PHONY : test workspace release install compile_commands debug run run_force test build build build-release ROOT_DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) @@ -24,10 +24,10 @@ workspace_v2: clean: $(ROOT_DIR)/tools/bazelwrapper clean -archive: build-release +release: build-release # Brew support -install: archive +install: release mkdir -p $(PREFIX)/bin ditto $(XCHAMMER_APP) $(PREFIX)/bin/$(PRODUCT) ln -s $(PREFIX)/bin/$(PRODUCT)/Contents/MacOS/xchammer $(PREFIX)/bin/xchammer diff --git a/README.md b/README.md index 366367a4..c3a602a9 100644 --- a/README.md +++ b/README.md @@ -32,20 +32,77 @@ XCHammer see [Introducing XCHammer](Docs/FastAndReproducibleBuildsWithXCHammer.md) and [Pinterest Focused Xcode Projects](PinterestFocusedXcodeProjects.md)_ -### Installation +### Bazel build Xcode projects -Build and install to `/usr/local/bin/` +First, pull XCHammer into the `WORKSPACE` file: -```bash -make install +_Ideally, pull in a release optimized binary build to keep XCHammer's +dependencies, Swift version, Xcode version, compiler flags, Bazel version, and +build time outside of the main iOS/macOS application's WORKSPACE. To easily +achieve this, GitHub CI creates a binary release artifact on receiving a new +tag._ + +```py +# WORKSPACE +# Recommended approach - the CI auto releases when you push a tag matching `v*` +# The release prefix is the _tested_ bazel version, and XCHammer is often +# forwards and backwards compatible +http_archive( + name = "xchammer", + urls = [ "https://github.com/pinterest/xchammer/releases/download/v3.4.1.0/xchammer.zip" ], +) + +# Download, unzip, and vendor a binary release of XCHammer from a GitHub +# action `artifact` on a PR +# https://github.com/pinterest/xchammer/pull/262/checks?check_run_id=1195532626 +# +# Note: the URL of these artifacts is directly consumeable with http_archive due +# to https://github.com/actions/upload-artifact/issues/50 +# local_repository( +# name = "xchammer", +# path = "tools/xchammer" +# ) + +# Pull from source +# git_repository( +# name = "xchammer", +# remote = "https://github.com/pinterest/xchammer.git", +# commit = "[COMMIT_SHA]" +# ) +``` +_note: for development, `make build` and the `xchammer_dev_repo` target allow a +WORKSPACE to consume XCHammer built out of tree but point to the latest build, +symlinked in `bazel-bin`: +`--override_repository=xchammer=/path/to/xchammer/bazel-bin/xchammer_dev_repo`. +It's also possible to use `local_repository` and override it using +`--override_repository=xchammer=/path/to/xchammer`_ + +Next, create an `xcode_project` target including targets: +``` +# BUILD.Bazel +load("@xchammer//:xcodeproject.bzl", "xcode_project") +xcode_project( + name = "MyProject", + targets = [ "//ios-app:ios-app" ], + paths = [ "**" ], +) ``` -_Pinterest vendors XCHammer.app for reproducibility and simplicity._ +Finally, build the project with Bazel +```bash +bazel build MyProject +``` +### CLI Usage ( Non Bazel built projects ) -### Configuration +XCHammer also works as a standalone project generator. kirst build XCHammer and +install to the path: -Generate using a [XCHammerConfig](Sources/XCHammer/XCHammerConfig.swift). +```bash +# Installs to `/usr/local/bin/` +make install +``` +Then, generate using a [XCHammerConfig](Sources/XCHammer/XCHammerConfig.swift). ```bash xchammer generate @@ -78,28 +135,6 @@ _To learn about how Pinterest uses XCHammer with Bazel locally check out [Pinter - [a Swift iOS app](sample/Tailor) - [a Swift macOS app](BUILD.bazel) -## Bazel build Xcode projects - -XCHammer additionally supports Bazel building Xcode projects, which enables -remote caching and other features. This feature is experimental. - -```py -# WORKSPACE -# TODO: binary releases will soon be created by the CI see -# https://github.com/pinterest/xchammer/pull/258 for more details. -http_archive( - name = "xchammer", - urls = [ "https://github.com/pinterest/xchammer/releases/download/${RELEASE}/TBD.zip" ], -) - -# BUILD.Bazel -load("@xchammer//:xcodeproject.bzl", "xcode_project") -xcode_project( - name = "MyProject", - targets = [ "//ios-app:ios-app" ], - paths = [ "**" ], -) -``` ### Xcode progress bar integration