Skip to content

Commit

Permalink
initial setup action script
Browse files Browse the repository at this point in the history
  • Loading branch information
miki725 committed Oct 3, 2023
1 parent f9a7c77 commit 684143d
Show file tree
Hide file tree
Showing 5 changed files with 304 additions and 0 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/setup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: setup

on:
pull_request:

permissions:
contents: read

jobs:
verify:
runs-on: ubuntu-latest

concurrency:
# only allow one job per PR running
# older pending jobs will be cancelled not to waste CI minutes
# cannot use github.job here https://github.com/community/community/discussions/13496
group: ${{ github.workflow }}-setup-${{ github.ref }}
cancel-in-progress: true

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Chalk
uses: ./

- name: Verify Setup
run: |
set -x
which chalk
which docker
echo 'log_level: "trace"' > /etc/chalk.conf
chalk version
docker version
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tags
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Setup Chalk

GitHub Action to setting up [Chalk].

This action will install `chalk` and will also wrap other commands
`chalk` supports such as `docker`.

## Usage

```yaml
name: ci

on:
push:

jobs:
buildx:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Chalk
uses: crashappsec/setup-chalk-version
```
## Customizing
The following parameters can be provided to the action.
| Name | Type | Default | Description |
| --------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------- |
| `version` | String | | Version of chalk to install. By default latest version is installed. See [releases] for all available versions. |
| `load` | String | | Chalk config to load. Can be either path to a file or an URL. |

For example:

```yaml
- name: Set up Chalk
uses: crashappsec/setup-chalk-version
with:
version: "0.1.2"
```

[chalk]: https://github.com/crashappsec/chalk/
[releases]: https://crashoverride.com/releases
24 changes: 24 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Setup Chalk
description: Install chalk and wrap supported commands

inputs:
version:
description: |
Version of chalk to install.
By default latest version is installed.
See https://crashoverride.com/releases for all available versions.
required: false
load:
description: |
Chalk config to load.
Can be either path to a file or an URL.
required: false

runs:
using: "composite"
steps:
- shell: bash
run: |
./setup.sh \
--version=${{ inputs.version }} \
--load=${{ inputs.load }}
200 changes: 200 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
#!/usr/bin/env bash

set -eEu
set -o pipefail

DEFAULT_CHALK_PATH=/usr/local/bin/chalk
WRAPPINGS_PATH=/usr/local/chalk
URL_PREFIX=https://crashoverride.com/dl/chalk
SHA256=sha256sum
TMP=/tmp

# on osx, sha256sum doesnt exist and instead its shasum
if [ -z "$(which $SHA256 2> /dev/null)" ]; then
SHA256="shasum -a 256"
fi

# version of chalk to download
version=
# which config to load after install
load=
# where chalk should be installed
chalk_path=
# tmp location for downloading chalk
chalk_tmp=
# whether to overwrite existing chalk binary
overwrite=true
# whether to wrap external commands with chalk
wrap=true

function log {
echo "$@" > /dev/stderr
}

# wrapper for calling chalk within the script
function chalk {
echo CHALK_PATH INSIDE "$chalk_path" > /dev/stderr
$chalk_path --log-level=error --skip-summary-report --skip-command-report "$@"
}

# find out latest chalk version
function get_latest_version {
log Querying latest version of chalk
version=$(curl -fsSL "$URL_PREFIX/current-version.txt")
log Latest version is "$version"
echo "$version"
}

# get the chalk file name for the version/os/architecture
function chalk_version_name {
echo "chalk-$version-$(uname -s)-$(uname -m)"
}

# download chalk and validate its checksum
function download_chalk {
url=$URL_PREFIX/$(chalk_version_name)
log Downloading chalk from "$url"
wget --content-on-error --quiet --directory-prefix=$TMP --unlink "$url"{,.sha256} || (
log Could not download "$(chalk_version_name)". Are you sure this is a valid version?
return 1
)
log Validating sha256 signature
$SHA256 "$chalk_tmp.sha256"
}

# validate downloaded chalk can run on the system
# and then install it to $chalk_path which should be on PATH
function install_chalk {
chmod +x "$chalk_tmp"
log Checking chalk version
$chalk_tmp version
log Installing chalk to "$chalk_path"
mkdir -p "$(dirname "$chalk_path")"
cp "$chalk_tmp" "$chalk_path"
}

# load custom chalk config
function load_config {
log Loading custom chalk config from "$load"
chalk load "$load"
}

# add line to config file if its not there already
function add_line_to_config {
line=$1
config=$2
if grep "$line" "$config" &> /dev/null; then
log "$cmd" path is already configured in chalk config
return 0
fi
log Adding "\"$line\"" to chalk config
echo >> "$config"
echo "$line" >> "$config"
}

# add necessary configs to wrap command with chalk
function add_cmd_exe_to_config {
cmd=$1
path=$2
folder=$(dirname "$path")
config=$(mktemp)
chalk dump > "$config"
add_line_to_config "default_command = \"$cmd\"" "$config"
add_line_to_config "${cmd}_exe = \"$folder\"" "$config"
chalk load "$config"
chalk dump
}

# wrap given command with chalk
function wrap_cmd {
cmd=$1
existing_path=$(which "$cmd" 2> /dev/null)
if [ -z "$existing_path" ]; then
log Skipping wrapping "$cmd" as it is not installed
return 0
fi

log Wrapping "$existing_path" command with chalk

# As we cant control PATH in CI, we copy original command
# to a chalk-specific location.
# Then well configure chalk to search for commands here
# and will replace the original binary with chalk.
# This way we chalk will still be able to find the original
# command and binary will still be in the same location.
new_path="$WRAPPINGS_PATH/$cmd"
sudo mkdir -p "$(dirname "$new_path")"
sudo cp "$existing_path" "$new_path"
log Moved "$existing_path" to "$new_path"

# create temporary chalk copy so that we can adjust its configuration
# to be able to find the moved binary in the custom location
tmp=$(mktemp)
cp "$chalk_path" "$tmp"
chalk_path=$tmp add_cmd_exe_to_config "$cmd" "$new_path"

sudo mv "$tmp" "$existing_path"
log Replaced "$existing_path" with chalk
}

for arg; do
shift
case "$arg" in
--version=*)
version=${arg##*=}
;;
--load=*)
load=${arg##*=}
;;
--chalk-path=*)
chalk_path=${arg##*=}
;;
--no-wrap)
wrap=
;;
--debug)
set -x
;;
--overwrite)
overwrite=true
;;
--no-overwrite)
overwrite=
;;
*)
set -- "$@" "$arg"
;;
esac
done

if [ -z "$chalk_path" ]; then
chalk_path=$(which chalk 2> /dev/null || true)
fi
if [ -z "$chalk_path" ]; then
chalk_path=$DEFAULT_CHALK_PATH
fi

if ! [ -f "$chalk_path" ] || [ -n "$overwrite" ]; then
if [ -f "$chalk_path" ]; then
log "$chalk_path" is already installed. overwriting
fi

if [ -z "$version" ]; then
version=$(get_latest_version)
fi

chalk_tmp=$TMP/$(chalk_version_name)

download_chalk
install_chalk
else
log "$chalk_path" is already installed. skipping
fi

if [ -n "$load" ]; then
load_config
fi

if [ -n "$wrap" ]; then
wrap_cmd docker
fi

0 comments on commit 684143d

Please sign in to comment.