summaryrefslogtreecommitdiff
path: root/src/scripts/build-action.sh
blob: 9c1d5022a48d2c6002ed038b1a835d616cebb32a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
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