diff options
Diffstat (limited to 'src/scripts/build-action.sh')
| -rw-r--r-- | src/scripts/build-action.sh | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/src/scripts/build-action.sh b/src/scripts/build-action.sh new file mode 100644 index 0000000..9c1d502 --- /dev/null +++ b/src/scripts/build-action.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +# kenku --- crawl and reproduce github actions +# Copyright © 2026 bdunahu <bdunahu@operationnull.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +function get_output_file { + local output_file action_file + action_file="action.yml" + [ ! -f "$action_file" ] && action_file="action.yaml" + output_file=$(grep -E '^\s*main:\s*' "${TO_ACT}${action_file}" | awk '{print $2}') + output_file=${output_file//\"/} + echo ${output_file//\'/} +} + +function script_exists { + npm run | grep -q "^ $1" +} + +ALL="$1" +SHA="$2" +DIR="$3" +BUILD_FAILURE_DIR="$4" +MISSING_ARTIFACT_DIR="$5" +MAYBE_REPRODUCIBLE_DIR="$6" +REPRODUCIBLE_DIR="$7" + +REPO_PRINTABLE="${ALL//\//_}_$SHA" +# holds temporary print strings + +REPO=$(echo "$ALL" | awk -F'/' '{print $(1)}') +TO_ACT=$(echo "$ALL" | awk -F'/' '{print $(2)}') +REPO="$REPO/$TO_ACT" +TO_ACT=$(echo "$ALL" | cut -d'/' -f3-) +[[ -n "$TO_ACT" ]] && TO_ACT="$TO_ACT/" + +BUILD_DIR=$(mktemp -d) +cd "$BUILD_DIR" + +echo "Cloning $REPO..." +git clone "https://github.com/$REPO.git" repo > /dev/null 2>&1 +cd repo +echo "Checking out $SHA" +git checkout "$SHA" > /dev/null 2>&1 + +# actions.yml refers to actions relatively, so if we parse +# ../dist/foo/ as the action final build dir, we need to +# refer to it relative to the curr dir of the script +# this is one way +DIST="$TO_ACT$(get_output_file)" +# some actions just name an index.js in the root dir. +# In cases they name a directory, we'll diff the full thing. +[ "$(dirname "$DIST")" != "." ] && DIST="$(dirname "$DIST")" +REFERENCE_DIST="$DIST.1" +echo "Saving $DIST to $REFERENCE_DIST" + +mv "$DIST" "$REFERENCE_DIST" + +cd "$DIR" +echo "Installing packages..." + +INSTALL=$(npm ci 2>&1) + +echo "Attempting to build..." + +TMP="owo what's the build command" +# surely ONE of these will work... +if COMM="release"; script_exists "$COMM"; then + echo "Trying '$COMM'..." + TMP=$(npm run "$COMM" 2>&1) +elif COMM="package"; script_exists "$COMM"; then + echo "Trying '$COMM'..." + TMP=$(npm run "$COMM" 2>&1) +elif COMM="bundle"; script_exists "$COMM"; then + echo "Trying '$COMM'..." + TMP=$(npm run "$COMM" 2>&1) +elif COMM="build"; script_exists "$COMM"; then + echo "Trying '$COMM'..." + TMP=$(npm run "$COMM" 2>&1) +fi + +# if the build fails, the developers may have failed to setup +# the environment properly, or it uses deprecated features. +# It may be that there is no build command at all! This needs +# manual review. +if [[ $? -ne 0 ]]; then + echo "$ALL did not build." + echo "$INSTALL" > "$BUILD_FAILURE_DIR/${REPO_PRINTABLE}.log" + echo "$TMP" >> "$BUILD_FAILURE_DIR/${REPO_PRINTABLE}.log" + exit 0 #don't kill outer script +fi + +# return back to where we were +cd "$BUILD_DIR" +cd repo + +if [[ ! -d "$DIST" ]]; then + # TODO: if the dist dir wasn't produced, then the commands + # used were likely wrong + echo "$ALL did not produce artifacts." + echo "$INSTALL" >> "$MISSING_ARTIFACT_DIR/${REPO_PRINTABLE}.log" + echo "$TMP" >> "$MISSING_ARTIFACT_DIR/${REPO_PRINTABLE}.log" + exit 0 +fi + +# diffoscope will output binary diffs if line endings are not +# comparable. --force forces it to convert binary files too. +find "$REFERENCE_DIST" -type f -exec dos2unix --force {} \; + +# TODO: solves path errors in containers when using global install +mkdir -p "$HOME/.npm-global" +npm config set prefix "$HOME/.npm-global" +export PATH="$HOME/.npm-global/bin:$PATH" + +# diffoscope uses to compare pretty +npm install -g js-beautify + +diffoscope "$DIST" "$REFERENCE_DIST" \ + --exclude-directory-metadata=yes \ + --html "$MAYBE_REPRODUCIBLE_DIR/${REPO_PRINTABLE}.html" +if [[ ! -f "$MAYBE_REPRODUCIBLE_DIR/${REPO_PRINTABLE}.html" ]]; then + touch "$REPRODUCIBLE_DIR/${REPO_PRINTABLE}.flag" + exit 0 +fi |
