Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/WORKFLOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -494,9 +494,11 @@ upstream:

1. Fetches the page: HTTPS only, at most 5 redirects and 5 MB.
2. Finds every match with `grep -oE`.
3. Extracts the first capture group with `sed -E`.
3. Takes the first capture group of each match with bash `[[ =~ ]]`, so the pattern may hold any character, `/` included.
4. Sorts with `sort -Vu` and returns the highest version.

`validate-pkg.sh` compiles the pattern with bash, which refuses some patterns that `grep -E` takes, `(?:...)` among them.

**Example YAML:**

```yaml
Expand Down
24 changes: 24 additions & 0 deletions scripts/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,30 @@ release_tags() {
grep -E '^v?[0-9]+(\.[0-9]+)*$' <<<"$1" || true
}

# The first capture group of every match of an ERE in stdin, one per line.
# grep finds the matches and bash takes the group, so no delimiter of a sed
# command limits the pattern.
# Args: $1=ERE with a capture group
capture_matches() {
local pattern="$1" match
while IFS= read -r match; do
if [[ "$match" =~ $pattern ]]; then
printf '%s\n' "${BASH_REMATCH[1]}"
fi
done < <(grep -oE -e "$pattern")
}

# Succeeds when bash accepts an ERE, as capture_matches needs. bash refuses
# some patterns that grep -E takes, (?:x) and *x among them.
# Args: $1=ERE
ere_valid() {
local rc=0
# [[ =~ ]] returns 2 for a pattern bash cannot compile
# shellcheck disable=SC2319
[[ "" =~ $1 ]] 2>/dev/null || rc=$?
((rc != 2))
}

# =============================================================================
# CHECKSUMS
# =============================================================================
Expand Down
6 changes: 2 additions & 4 deletions scripts/validate-pkg.sh
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,8 @@ validate_pkg() {
log_err "$file: strategy 'webpage-scrape' requires 'upstream.pattern'"
((errors++))
else
# Validate regex syntax: grep exits 2 on invalid regex
local grep_rc=0
echo "" | grep -qE -e "$pattern" 2>/dev/null || grep_rc=$?
if [[ "$grep_rc" -eq 2 ]]; then
# The strategy runs the pattern through grep and bash
if ! ere_valid "$pattern"; then
log_err "$file: upstream.pattern is not valid ERE regex: $pattern"
((errors++))
fi
Expand Down
5 changes: 2 additions & 3 deletions strategies/webpage-scrape.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,8 @@ page=$(http_get "$url" --max-redirs 5 --max-filesize "$MAX_SIZE" -A "Mozilla/5.0
exit 1
}

# Extract versions using ERE, capture group via sed. The pattern can close
# the s command; --sandbox refuses e, r and w
versions=$(echo "$page" | grep -oE -e "$pattern" | sed --sandbox -E "s/$pattern/\\1/" | sort -Vu)
# The first capture group of every match
versions=$(echo "$page" | capture_matches "$pattern" | sort -Vu)

if [[ -z "$versions" ]]; then
echo "No versions matched pattern '$pattern' at $url" >&2
Expand Down
13 changes: 12 additions & 1 deletion tests/strategies.bats
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,16 @@ teardown() {
[ "$output" = "7.0.0" ]
}

@test "webpage-scrape: a pattern may hold a slash" {
create_test_package "test-scrape-path" "webpage-scrape" "upstream:
url: https://example.com/releases
pattern: 'download/test-scrape-([0-9.]+)\\.tar\\.gz'"

run "$TEST_TMPDIR/strategies/webpage-scrape.sh" "test-scrape-path"
[ "$status" -eq 0 ]
[ "$output" = "7.0.0" ]
}

# === git-latest ===

@test "git-latest: returns rCOUNT.HASH format from git repo" {
Expand Down Expand Up @@ -384,8 +394,9 @@ teardown() {

cd "$TEST_TMPDIR"
run "$TEST_TMPDIR/strategies/webpage-scrape.sh" "test-scrape-exec"
[ "$status" -ne 0 ]
[ ! -e "$TEST_TMPDIR/pwned" ]
[ "$status" -eq 0 ]
[ "$output" = "7" ]
}

@test "webpage-scrape: a pattern may start with a dash" {
Expand Down
21 changes: 21 additions & 0 deletions tests/validate-pkg.bats
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,27 @@ EOF
[ "$status" -eq 0 ]
}

# grep -E takes these and bash refuses them
@test "validate: webpage-scrape rejects a pattern that bash cannot compile" {
local pattern
for pattern in '(?:v)?pkg-([0-9.]+)' '*pkg-([0-9.]+)' 'pkg-([0-9]{1)'; do
create_test_package "mypkg" "webpage-scrape" "upstream:
url: https://example.com/releases
pattern: '$pattern'"
run "$TEST_TMPDIR/scripts/validate-pkg.sh" "mypkg"
[ "$status" -ne 0 ]
[[ "$output" == *"not valid ERE regex"* ]]
done
}

@test "validate: webpage-scrape accepts a pattern with a slash" {
create_test_package "mypkg" "webpage-scrape" "upstream:
url: https://example.com/releases
pattern: 'download/pkg-([0-9.]+)\\.tar\\.gz'"
run "$TEST_TMPDIR/scripts/validate-pkg.sh" "mypkg"
[ "$status" -eq 0 ]
}

@test "validate: webpage-scrape rejects invalid regex pattern" {
create_test_package "mypkg" "webpage-scrape" "upstream:
url: https://example.com/releases
Expand Down
Loading