Skip to content

Commit

Permalink
Merge pull request #59 from EOSIO/zach-ci
Browse files Browse the repository at this point in the history
Create homebrew-eosio Pipeline
  • Loading branch information
kj4ezj authored Jul 14, 2021
2 parents 5b3d535 + 81a0013 commit 9ba168c
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 1 deletion.
52 changes: 52 additions & 0 deletions .ci/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# homebrew-eosio
The [homebrew-eosio](https://buildkite.com/EOSIO/homebrew-eosio) pipeline runs on the `master` branch of the [homebrew-eosio](https://github.com/EOSIO/homebrew-eosio) repo to verify that the [EOSIO](https://github.com/EOSIO/eos) packages we are providing via the [Homebrew](https://brew.sh) package manager on macOS are functional.

<details>
<summary>See More</summary>

## Index
1. [Test](README.md#test)
1. [Configuration](README.md#configuration)
1. [Variables](README.md#variables)
1. [Examples](README.md#examples)
1. [Pipelines](README.md#pipelines)
1. [See Also](README.md#see-also)

# Test
This pipeline will parse the [eosio.rb](https://github.com/EOSIO/homebrew-eosio/blob/master/eosio.rb) ruby file in the root of this repo and generate a pipeline step to run a clean Anka VM for each macOS version found. Each step performs the following:
1. Verify the SHA-256 of the bottle attached to the release on GitHub at `root_url` in the ruby file matches the hash defined in the ruby file
1. Tap EOSIO
```bash
brew tap EOSIO/eosio
```
1. Install EOSIO
```bash
brew install eosio
```
1. Look for the `nodeos` binary
```bash
which nodeos
```
1. Invoke the [full-version-label.sh](https://github.com/EOSIO/eos/blob/master/tests/full-version-label.sh) test on that binary

All of these must pass for the Buildkite job step to pass.

# Configuration
There are no user-configurable options for this pipeline at this time. The functionality of this pipeline is based entirely on the `eosio.rb` ruby file in the root of [homebrew-eosio](https://github.com/EOSIO/homebrew-eosio) on the `master` branch.

## Variables
There are no configurable variables intended for the end-user at this time.

Because this pipeline runs against published release packages, it doesn't make sense to run it on feature branches. If you try, the pipeline fails with a useful error message. We did create a flag to bypass this so engineers can test changes to the CI code on feature branches.
```bash
DEBUG='true|false' # run this pipeline on feature branches, for testing CI changes
```

# See Also
- Buildkite
- [DevDocs](https://github.com/EOSIO/devdocs/wiki/Buildkite)
- [EOSIO Pipelines](https://github.com/EOSIO/eos/blob/master/.cicd/README.md)
- [Run Your First Build](https://buildkite.com/docs/tutorials/getting-started#run-your-first-build)
- [#help-automation](https://blockone.slack.com/archives/CMTAZ9L4D) Slack Channel

</details>
34 changes: 34 additions & 0 deletions .ci/anka.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
- label: ":darwin: macOS ${OS_STYLIZED} - ${LABEL}"
command:
- "git clone --recursive --single-branch --branch '${BUILDKITE_BRANCH}' '${BUILDKITE_REPO}'"
- "./${BUILDKITE_PIPELINE_SLUG}/.ci/test.sh"
env:
BIN: "${BIN}"
BOTTLE: "${BOTTLE}"
GIT_TAG: "${TAG}"
OS: "${OS}"
OS_STYLIZED: "${OS_STYLIZED}"
PACKAGE: "${PACKAGE}"
REPO_UNDER_TEST: "${REPO_UNDER_TEST}"
ROOT_URL: "${ROOT_URL}"
RUBY_FILE: "${RUBY_FILE}"
TAP: "${TAP}"
plugins:
- EOSIO/anka#v0.6.1:
always-pull: true
debug: true
failover-registries:
- "registry_1"
- "registry_2"
inherit-environment-vars: true
no-volume: true
pre-execute-ping-sleep: github.com
pre-execute-sleep: 5
vm-name: "${VM}"
vm-registry-tag: "${ANKA_LAYERS}"
wait-network: true
- EOSIO/skip-checkout#v0.1.1:
cd: ~
agents: "queue=mac-anka-node-fleet"
timeout: ${TIMEOUT:-18}

55 changes: 55 additions & 0 deletions .ci/pipeline-upload.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash
set -eo pipefail
echo '+++ :evergreen_tree: Configuring Environment' >&2
export ANKA_LAYERS='clean::cicd::git-ssh::nas::brew::buildkite-agent'
export AMKA_VM_MAP='{"mojave":"10.14.6_6C_14G_80G","catalina":"10.15.5_6C_14G_80G","big_sur":"11.2.1_6C_14G_80G"}'
export BIN='nodeos'
export PACKAGE='eosio'
export REPO_UNDER_TEST='git@github.com:EOSIO/eos.git'
export RETRY="$([[ "$BUILDKITE" == 'true' ]] && buildkite-agent meta-data get pipeline-upload-retries --default '0' || echo '0')"
export RUBY_FILE='eosio.rb'
export ROOT_URL="$(cat "$RUBY_FILE" | grep -P '^\s+root_url' | head -1 | awk '{print $2}' | tr -d '"')"
echo "Found root URL \"$ROOT_URL\"." >&2
export TAG="v$(cat "$RUBY_FILE" | grep -P '^\s+version' | awk '{print $2}' | tr -d '"')"
echo "Found git tag '$TAG'." >&2
export TAP='EOSIO/eosio'
[[ "$BUILDKITE" == 'true' ]] && buildkite-agent meta-data set pipeline-upload-retries "$(( $RETRY + 1 ))"
# attach pipeline documentation
echo '+++ :md: Attaching Documentation'
export DOCS_URL="https://github.com/EOSIO/homebrew-eosio/blob/${BUILDKITE_COMMIT:-master}/.ci/README.md"
if [[ "$BUILDKITE" == 'true' && "$RETRY" == '0' ]]; then
echo "This documentation is also available on [GitHub]($DOCS_URL)." | buildkite-agent annotate --append --style 'info' --context 'documentation'
cat .ci/README.md | buildkite-agent annotate --append --style 'info' --context 'documentation'
elif [[ "$BUILDKITE" == 'true' ]]; then
printf "Skipping \033]1339;url=$DOCS_URL;content=documentation\a upload for job retry number $RETRY.\n" >&2
fi
# only run on master
if [[ "$BUILDKITE_BRANCH" != 'master' && "$DEBUG" != 'true' ]]; then
ERROR_MSG='This pipeline currently does nothing on branches besides `master`!'
echo "ERROR: $ERROR_MSG" | tr -d '`' | cat >&2
[[ "$BUILDKITE" == 'true' && "$RETRY" == '0' ]] && echo "**ERROR:** $ERROR_MSG" | buildkite-agent annotate --style 'error' --context 'not-master'
exit 1
elif [[ "$DEBUG" == 'true' ]]; then
WARNING_MSG='Running on non-`master` branch because `DEBUG` is set to "true".'
echo "WARNING: $WARNING_MSG" | tr -d '`' | cat >&2
[[ "$BUILDKITE" == 'true' && "$RETRY" == '0' ]] && echo "**WARNING:** $WARNING_MSG" | tr '"' '`' | buildkite-agent annotate --style 'warning' --context 'not-master'
fi
echo '+++ :yaml: Generating Pipeline Steps' >&2
# yaml header
cat <<EOF
steps:
- wait
EOF
# parse ruby file and generate pipeline steps
export LABEL='Homebrew Package Validation'
for OS in $(cat "$RUBY_FILE" | grep -P '^\s+sha256' | awk '{print $2}' | tr -d ':'); do
export BOTTLE="eosio-$(echo "$TAG" | tr -d 'v').$OS.bottle.tar.gz"
export OS="$OS" # for jq env command
export OS_STYLIZED="$(echo "$OS" | sed -e 's/\b\(.\)/\u\1/g')"
echo "Found $OS operating system." >&2
export VM="$(echo "$AMKA_VM_MAP" | jq -r '.[env.OS]')"
cat .ci/anka.yml | envsubst '$ANKA_LAYERS $BIN $BOTTLE $BUILDKITE_PIPELINE_SLUG $BUILDKITE_REPO $LABEL $OS $OS_STYLIZED $PACKAGE $REPO_UNDER_TEST $ROOT_URL $RUBY_FILE $TAG $TAP $VM'
done
echo '--- :white_check_mark: Done! Good luck :)' >&2
echo 'Done.' >&2
73 changes: 73 additions & 0 deletions .ci/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash
set -eo pipefail
echo '--- :evergreen_tree: Configuring Environment'
exec 9>&1 # enable tee to write to STDOUT as a file
echo "Using git tag '$REPO_UNDER_TEST:$GIT_TAG'."
CLONE="git clone --recursive --single-branch --branch '${GIT_TAG}' '${REPO_UNDER_TEST}'"
echo "$ $CLONE"
eval $CLONE
BREW_UPDATE='brew update'
echo "$ $BREW_UPDATE"
eval $BREW_UPDATE
if [[ ! -z "$BOTTLE" ]]; then
echo '+++ :hash: Verify Package Hash - SHA-256'
cd "$BUILDKITE_PIPELINE_SLUG" # same as repo name
DOWNLOAD="curl -fsSL -o './$BOTTLE' '$ROOT_URL/$BOTTLE'"
echo "$ $DOWNLOAD"
eval $DOWNLOAD
FILE_HASH="openssl dgst -sha256 '$BOTTLE'"
echo "$ $FILE_HASH"
BOTTLE_HASH="$(eval $FILE_HASH | tee >(cat - >&9) | awk '{print $2}')"
RUBY_LINE="cat '$RUBY_FILE' | grep 'sha256' | grep '$OS'"
echo "$ $RUBY_LINE"
RUBY_HASH="$(eval $RUBY_LINE | tee >(cat - >&9) | awk '{print $3}' | tr -d '"')"
if [[ "$BOTTLE_HASH" == "$RUBY_HASH" ]]; then
echo "Pass: $BOTTLE_HASH = $RUBY_HASH"
else
echo "+++ :x: Failed to Verify Bottle Hash"
FAIL_MSG="$BOTTLE hash $BOTTLE_HASH$RUBY_FILE::$OS hash $RUBY_HASH"'!'
echo "FAILURE: $FAIL_MSG"
[[ "$BUILDKITE" == 'true' ]] && echo "**FAILURE:** $FAIL_MSG" | buildkite-agent annotate --style 'error' --context "wrong-hash-$OS"
exit 2
fi
cd ..
fi
echo '+++ :beer: Homebrew Tap and Install'
BREW_TAP="brew tap '$TAP'"
echo "$ $BREW_TAP"
eval $BREW_TAP
BREW_INSTALL="brew install '$PACKAGE'"
echo "$ $BREW_INSTALL"
eval $BREW_INSTALL
echo '+++ :label: Full Version Label Test'
cd eos
WHICH_BIN="which '$BIN'"
echo "$ $WHICH_BIN"
export BUILD_ROOT="$(eval $WHICH_BIN | tee >(cat - >&9) | sed "s_/bin/${BIN}__g")"
if [[ -z "$BUILD_ROOT" ]]; then
FAIL_MSG="'$BIN' binary not found after homebrew installation on $OS_STYLIZED"'!'
echo "FAILURE: $FAIL_MSG"
[[ "$BUILDKITE" == 'true' ]] && echo "**FAILURE:** $FAIL_MSG" | tr "'" '`' | buildkite-agent annotate --style 'error' --context "no-binary-$OS"
exit 3
else
echo "Found '$BIN' at \"$BUILD_ROOT/bin/$BIN\"."
fi
export BUILDKITE_COMMIT="$(git rev-parse HEAD)" # override homebrew-eosio commit with eos tag commit
echo "Found git commit '$REPO_UNDER_TEST:$BUILDKITE_COMMIT'."
unset BUILDKITE_TAG
export CMAKE_SOURCE_DIR="$(pwd)"
echo "Set CMAKE_SOURCE_DIR to \"$CMAKE_SOURCE_DIR\"."
TEST="./tests/full-version-label.sh '$GIT_TAG'"
echo "$ $TEST"
set +e
eval $TEST
EXIT_STATUS="$?"
set -e
if [[ "$EXIT_STATUS" != '0' ]]; then
FAIL_MSG="Version label test failed on $OS_STYLIZED"'!'
echo "FAILURE: $FAIL_MSG"
[[ "$BUILDKITE" == 'true' ]] && echo "**FAILURE:** $FAIL_MSG" | buildkite-agent annotate --style 'error' --context "test-failure-$OS"
exit "$EXIT_STATUS"
fi
echo '--- :white_check_mark: Done!'
echo 'Done.'
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# homebrew-eosio
This repository is a "[tap](https://docs.brew.sh/Taps)" for `homebrew`, a macOS package manager. When you run `brew install eosio` or `brew upgrade`, `brew` will look here to determine where to find the latest macOS binaries for EOSIO.
This repository is a "[tap](https://docs.brew.sh/Taps)" for [Homebrew](https://brew.sh), a macOS package manager. When you run `brew install eosio` or `brew upgrade`, `brew` will look here to determine where to find the latest macOS binaries for [EOSIO](https://github.com/EOSIO/eos).

The [homebrew-eosio](https://buildkite.com/EOSIO/homebrew-eosio) pipeline runs against the `master` branch of this repo to verify that the [EOSIO](https://github.com/EOSIO/eos) packages we are providing via `brew` can be installed and invoked without errors on clean installations of their respective macOS versions. It also verifies the SHA-256 of the bottle matches the tap here, and the version string of the binary matches our CMake.

## Automation
The [eosioBrewAutoPR](https://github.com/EOSIO/auto-events-subscribers/blob/master/lambdas/eosioBrewAutoPR.js) [lambda](https://en.wikipedia.org/wiki/AWS_Lambda) recieves a [webhook](https://en.wikipedia.org/wiki/Webhook) (event notification) any time a Buildkite step finishes across the [EOSIO organization](http://buildkite.com/EOSIO).
Expand Down

0 comments on commit 9ba168c

Please sign in to comment.