-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcli.sh
More file actions
188 lines (166 loc) · 6.39 KB
/
Copy pathcli.sh
File metadata and controls
188 lines (166 loc) · 6.39 KB
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
#!/usr/bin/env bash -il
GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
SCRIPT_PATH=$(realpath --relative-to="$GIT_ROOT" "$0" 2>/dev/null || realpath "$0")
SUBCOMMAND="$1"
EXTRA_ARGS=$@
CACHE_ROOT="${HOME}/.cache/browserstack/devtools/cli/"
BINARY_ZIP_PATH="${CACHE_ROOT}/browserstack-cli.zip"
BINARY_PATH="${CACHE_ROOT}/browserstack-cli"
mkdir -p "$CACHE_ROOT"
get_os() {
local uname_out
uname_out="$(uname -s)"
case "${uname_out}" in
Linux*) os_type=linux;;
Darwin*) os_type=macos;;
*) os_type="UNKNOWN:${uname_out}"
esac
echo "${os_type}"
}
get_arch() {
local arch_out
arch_out="$(uname -m)"
case "${arch_out}" in
x86_64*) arch_type=x64;;
arm64*) arch_type=arm64;;
*) arch_type="UNKNOWN:${arch_out}"
esac
echo "${arch_type}"
}
OS=$(get_os)
ARCH=$(get_arch)
register_git_hook() {
local hook_name="pre-commit"
local hook_path="${GIT_ROOT}/.git/hooks/${hook_name}"
# Check if the hook file already exists
if [ -f "${hook_path}" ]; then
# Append the script execution if not already present
if ! grep -q "${SCRIPT_PATH}" "${hook_path}"; then
echo "" >> "${hook_path}"
echo "# Hook to run accessibility scan before commit" >> "${hook_path}"
echo "${SCRIPT_PATH}" >> "${hook_path}"
echo "if [ \$? -ne 0 ]; then" >> "${hook_path}"
echo " echo \"Accessibility scan failed. Commit aborted.\"" >> "${hook_path}"
echo " exit 1" >> "${hook_path}"
echo "fi" >> "${hook_path}"
fi
else
# Create a new hook file
cat > "${hook_path}" <<EOF
#!/bin/sh
# Hook to run accessibility scan before commit
"${SCRIPT_PATH}"
if [ \$? -ne 0 ]; then
echo "Accessibility scan failed. Commit aborted."
exit 1
fi
EOF
chmod +x "${hook_path}" # Make the hook executable
fi
}
a11y_scan() {
if [[ -z "$EXTRA_ARGS" ]]; then
EXTRA_ARGS="--include **/*.swift --include **/*.xib --include **/*.storyboard"
fi
env -i HOME="$HOME" \
XCODE_VERSION_ACTUAL="$XCODE_VERSION_ACTUAL"\
BROWSERSTACK_USERNAME="$BROWSERSTACK_USERNAME"\
BROWSERSTACK_ACCESS_KEY="$BROWSERSTACK_ACCESS_KEY"\
PATH="$PATH" \
$BINARY_PATH a11y $EXTRA_ARGS
}
# Self-update tracks the latest launcher on `main` so users always run the
# newest version. DEVA11Y-475/477/478: we deliberately follow main HEAD rather
# than a pinned revision (per maintainer intent: always take the latest).
# Hardening retained from the pinning work: download to a temp dir, verify a
# SHA-256 sidecar (a download-integrity check, NOT an authenticity signature --
# script and checksum share one origin), sanity-check the shebang, then
# atomically replace the on-disk script. Keep scripts/bash/cli.sh.sha256 on main in
# sync with this file (regenerate on every change) or updates will abort.
SELF_UPDATE_BRANCH="main"
readonly SELF_UPDATE_BRANCH
SELF_UPDATE_RELPATH="scripts/bash/cli.sh"
readonly SELF_UPDATE_RELPATH
# sha256 with a portable fallback: GNU `sha256sum` (Linux) or `shasum -a 256`
# (macOS / Perl Digest::SHA).
_self_update_sha256() {
if command -v sha256sum >/dev/null 2>&1; then
sha256sum "$1" | awk '{print $1}'
else
shasum -a 256 "$1" | awk '{print $1}'
fi
}
script_self_update() {
local base_url="https://raw.githubusercontent.com/browserstack/AccessibilityDevTools/refs/heads/${SELF_UPDATE_BRANCH}/${SELF_UPDATE_RELPATH}"
local tmp_dir tmp_script tmp_sum expected_sum actual_sum local_sum target_path stage_file
# Resolve the on-disk target absolutely so the replace never depends on CWD.
if [[ -n "$GIT_ROOT" && "$SCRIPT_PATH" != /* ]]; then
target_path="${GIT_ROOT}/${SCRIPT_PATH}"
else
target_path="$SCRIPT_PATH"
fi
tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/bs-a11y-selfupdate.XXXXXX") || {
echo "Self-update: failed to create temp dir." >&2
return 1
}
# shellcheck disable=SC2064
trap "rm -rf -- '${tmp_dir}'" RETURN
tmp_script="${tmp_dir}/cli.sh"
tmp_sum="${tmp_dir}/cli.sh.sha256"
# Fetch the checksum first; if our on-disk copy already matches, we're current.
if ! curl -fsSL --connect-timeout 10 --max-time 30 "${base_url}.sha256" -o "$tmp_sum"; then
echo "Self-update: could not fetch checksum from ${SELF_UPDATE_BRANCH}; skipping update." >&2
return 0
fi
# Published sidecar is "<sha256> <filename>"; take the first field.
expected_sum=$(awk '{print $1; exit}' "$tmp_sum")
if [[ -f "$target_path" ]]; then
local_sum=$(_self_update_sha256 "$target_path")
if [[ -n "$expected_sum" && "$local_sum" == "$expected_sum" ]]; then
return 0
fi
fi
if ! curl -fsSL --connect-timeout 10 --max-time 30 "$base_url" -o "$tmp_script"; then
echo "Self-update: could not download latest script; skipping update." >&2
return 0
fi
actual_sum=$(_self_update_sha256 "$tmp_script")
if [[ -z "$expected_sum" || -z "$actual_sum" || "$expected_sum" != "$actual_sum" ]]; then
echo "Self-update: checksum mismatch; refusing to apply." >&2
echo " expected: ${expected_sum:-<empty>}" >&2
echo " actual: ${actual_sum:-<empty>}" >&2
return 1
fi
# Sanity check AFTER integrity: ensure the verified payload is a script.
if ! head -c2 "$tmp_script" | grep -q '^#!'; then
echo "Self-update: downloaded file is not a script; aborting." >&2
return 1
fi
# Stage inside the target's directory so the rename is atomic (mv across
# filesystems would degrade to a non-atomic copy).
stage_file=$(mktemp "$(dirname "$target_path")/.bs-a11y-update.XXXXXX") || {
echo "Self-update: failed to stage update next to ${target_path}." >&2
return 1
}
if cp "$tmp_script" "$stage_file" && chmod 0755 "$stage_file" && mv -f "$stage_file" "$target_path"; then
echo "Self-update: updated ${target_path} to latest ${SELF_UPDATE_BRANCH}."
else
rm -f -- "$stage_file"
echo "Self-update: failed to replace ${target_path}." >&2
return 1
fi
}
download_binary() {
curl -R -z "$BINARY_ZIP_PATH" -L "https://api.browserstack.com/sdk/v1/download_cli?os=${OS}&os_arch=${ARCH}" -o "$BINARY_ZIP_PATH"
bsdtar -xvf "$BINARY_ZIP_PATH" -O > "$BINARY_PATH" && chmod 0775 "$BINARY_PATH"
}
# Best-effort auto-update: always fetch the latest launcher from main before
# running. Failures (offline, integrity) are non-fatal -- the current script
# keeps working and any update applies on the next invocation.
script_self_update || true
if [[ $SUBCOMMAND == "register-pre-commit-hook" ]]; then
register_git_hook
exit 0
fi
download_binary
a11y_scan