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
115 changes: 38 additions & 77 deletions .github/workflows/test-breaking.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -276,105 +276,66 @@ jobs:
breaking_free_review_url_preserves_https_base:
runs-on: ubuntu-latest
name: Test breaking free review URL keeps the https:// scheme on URL-style base
# Regression test for the bug class fixed in pr-comment (#120): the naive
# base_path=$(echo "$base" | sed 's/.*://') strips "https:" from a
# URL-shaped base and leaves a broken "//raw.github..." in the free
# /review link, which the page renders as a misleading access-denied
# screen. The strip_ref_prefix helper passes URLs through unchanged.
# Regression test for the bug fixed in pr-comment (#120): a URL-shaped base
# must survive intact in the review URL's base_file, not be mangled to
# "//raw.github..." by the git-ref-prefix strip. Runs the real action in its
# Alpine container (the production platform) and asserts on the review_url
# output. openapi-test1 -> openapi-test3 has breaking changes, so the notice
# (and review_url) fire.
steps:
- uses: actions/checkout@v6
- name: Stub oasdiff to report a change so the notice fires
- uses: ./breaking
id: brk
with:
base: 'https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test1.yaml'
revision: 'https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test3.yaml'
- name: Assert the full https:// URL is preserved in base_file
env:
REVIEW_URL: ${{ steps.brk.outputs.review_url }}
run: |
set -euo pipefail
mkdir -p /tmp/stub
cat > /tmp/stub/oasdiff <<'STUB'
#!/bin/sh
echo '1 breaking change(s)'
STUB
chmod +x /tmp/stub/oasdiff

mkdir -p /tmp/run
export GITHUB_REPOSITORY=oasdiff-test/test
export GITHUB_SHA=deadbeef
export GITHUB_BASE_REF=main
export GITHUB_OUTPUT=/tmp/run/github-output
export GITHUB_STEP_SUMMARY=/tmp/run/step-summary
cat > /tmp/run/event.json <<EVT
{"pull_request":{"head":{"sha":"deadbeef"},"base":{"sha":"baadcafe"}}}
EVT
export GITHUB_EVENT_PATH=/tmp/run/event.json

export PATH=/tmp/stub:$PATH
base_url='https://raw.githubusercontent.com/oasdiff-test/test/main/simple.yaml'
out=$(./breaking/entrypoint.sh \
"$base_url" 'simple.yaml' \
'' '' '' '' '' '' '' '' '' '' '' '' 2>&1)
echo "--- entrypoint output ---"
echo "$out"

if ! echo "$out" | grep -q "::notice::.*breaking changes"; then
echo "FAIL: review-URL notice line missing" >&2
echo "review_url=$REVIEW_URL"
if [ -z "$REVIEW_URL" ]; then
echo "FAIL: review_url output is empty (expected breaking changes to fire the notice)" >&2
exit 1
fi
notice=$(echo "$out" | grep "::notice::.*breaking changes")
if echo "$notice" | grep -q 'base_file=https%3A%2F%2Fraw.githubusercontent.com'; then
if printf '%s' "$REVIEW_URL" | grep -q 'base_file=https%3A%2F%2Fraw.githubusercontent.com'; then
echo "PASS: full https://raw... URL preserved in base_file"
elif echo "$notice" | grep -q 'base_file=%2F%2Fraw.githubusercontent.com'; then
elif printf '%s' "$REVIEW_URL" | grep -q 'base_file=%2F%2Fraw.githubusercontent.com'; then
echo "FAIL: 'https:' was stripped from base, the strip_ref_prefix URL guard is missing" >&2
echo "notice line: $notice" >&2
exit 1
else
echo "FAIL: base_file= param did not contain the raw.githubusercontent.com host as expected" >&2
echo "notice line: $notice" >&2
echo "FAIL: base_file= did not contain the raw.githubusercontent.com host as expected" >&2
exit 1
fi

breaking_free_review_url_strips_git_ref_prefix:
runs-on: ubuntu-latest
name: "Test breaking free review URL strips origin/main: prefix from git-ref base"
# Companion to breaking_free_review_url_preserves_https_base: a git-ref
# base (origin/main:openapi.yaml) must still have its prefix stripped so
# the /review page receives just the path.
name: "Test breaking free review URL strips the ref: prefix from a git-ref base"
# Companion to the preserve test: a git-ref base (HEAD:specs/base.yaml) must
# have its ref prefix stripped so base_file is just the path. Also exercises
# real git-ref resolution, the action's recommended base form.
steps:
- uses: actions/checkout@v6
- name: Stub oasdiff to report a change so the notice fires
- uses: ./breaking
id: brk
with:
base: 'HEAD:specs/base.yaml'
revision: 'specs/revision-breaking.yaml'
- name: Assert the git-ref prefix is stripped from base_file
env:
REVIEW_URL: ${{ steps.brk.outputs.review_url }}
run: |
set -euo pipefail
mkdir -p /tmp/stub
cat > /tmp/stub/oasdiff <<'STUB'
#!/bin/sh
echo '1 breaking change(s)'
STUB
chmod +x /tmp/stub/oasdiff

mkdir -p /tmp/run
export GITHUB_REPOSITORY=foo/bar
export GITHUB_SHA=deadbeef
export GITHUB_BASE_REF=main
export GITHUB_OUTPUT=/tmp/run/github-output
export GITHUB_STEP_SUMMARY=/tmp/run/step-summary
cat > /tmp/run/event.json <<EVT
{"pull_request":{"head":{"sha":"deadbeef"},"base":{"sha":"baadcafe"}}}
EVT
export GITHUB_EVENT_PATH=/tmp/run/event.json

export PATH=/tmp/stub:$PATH
out=$(./breaking/entrypoint.sh \
'origin/main:multi-file/openapi.yaml' 'HEAD:multi-file/openapi.yaml' \
'' '' '' '' '' '' '' '' '' '' '' '' 2>&1)
echo "--- entrypoint output ---"
echo "$out"

if ! echo "$out" | grep -q "::notice::.*breaking changes"; then
echo "FAIL: review-URL notice line missing" >&2
echo "review_url=$REVIEW_URL"
if [ -z "$REVIEW_URL" ]; then
echo "FAIL: review_url output is empty (expected breaking changes to fire the notice)" >&2
exit 1
fi
notice=$(echo "$out" | grep "::notice::.*breaking changes")
if echo "$notice" | grep -q 'base_file=multi-file%2Fopenapi.yaml'; then
echo "PASS: origin/main: prefix stripped from base"
if printf '%s' "$REVIEW_URL" | grep -q 'base_file=specs%2Fbase.yaml'; then
echo "PASS: ref prefix stripped from base"
else
echo "FAIL: base_file= did not have the git-ref prefix stripped" >&2
echo "notice line: $notice" >&2
echo "FAIL: base_file= did not have the git-ref prefix stripped (got: $REVIEW_URL)" >&2
exit 1
fi

114 changes: 36 additions & 78 deletions .github/workflows/test-changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -90,106 +90,64 @@ jobs:
changelog_free_review_url_preserves_https_base:
runs-on: ubuntu-latest
name: Test changelog free review URL keeps the https:// scheme on URL-style base
# Regression test for the bug class fixed in pr-comment (#120): a
# URL-shaped base must survive intact in the free /review link rather
# than being mangled to "//raw.github..." by the naive ref-prefix strip.
# Regression test for the bug fixed in pr-comment (#120): a URL-shaped base
# must survive intact in the review URL's base_file. Runs the real action in
# its Alpine container (the production platform) and asserts on the
# review_url output.
steps:
- uses: actions/checkout@v6
- name: Stub oasdiff to report a change so the notice fires
- uses: ./changelog
id: clog
with:
base: 'https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test1.yaml'
revision: 'https://raw.githubusercontent.com/oasdiff/oasdiff/main/data/openapi-test3.yaml'
- name: Assert the full https:// URL is preserved in base_file
env:
REVIEW_URL: ${{ steps.clog.outputs.review_url }}
run: |
set -euo pipefail
mkdir -p /tmp/stub
cat > /tmp/stub/oasdiff <<'STUB'
#!/bin/sh
echo '1 change(s)'
STUB
chmod +x /tmp/stub/oasdiff

mkdir -p /tmp/run
export GITHUB_REPOSITORY=oasdiff-test/test
export GITHUB_SHA=deadbeef
export GITHUB_BASE_REF=main
export GITHUB_OUTPUT=/tmp/run/github-output
export GITHUB_STEP_SUMMARY=/tmp/run/step-summary
cat > /tmp/run/event.json <<EVT
{"pull_request":{"head":{"sha":"deadbeef"},"base":{"sha":"baadcafe"}}}
EVT
export GITHUB_EVENT_PATH=/tmp/run/event.json

export PATH=/tmp/stub:$PATH
base_url='https://raw.githubusercontent.com/oasdiff-test/test/main/simple.yaml'
# Invoke with bash: the entrypoint's #!/bin/sh is dash on the runner,
# which rejects `set -o pipefail` (exit 2). In production it runs under
# the container's busybox ash, which supports it.
out=$(bash ./changelog/entrypoint.sh \
"$base_url" 'simple.yaml' \
'' '' '' '' '' '' '' '' '' '' '' '' 2>&1)
echo "--- entrypoint output ---"
echo "$out"

if ! echo "$out" | grep -q "::notice::.*API changes"; then
echo "FAIL: review-URL notice line missing" >&2
echo "review_url=$REVIEW_URL"
if [ -z "$REVIEW_URL" ]; then
echo "FAIL: review_url output is empty (expected changes to fire the notice)" >&2
exit 1
fi
notice=$(echo "$out" | grep "::notice::.*API changes")
if echo "$notice" | grep -q 'base_file=https%3A%2F%2Fraw.githubusercontent.com'; then
if printf '%s' "$REVIEW_URL" | grep -q 'base_file=https%3A%2F%2Fraw.githubusercontent.com'; then
echo "PASS: full https://raw... URL preserved in base_file"
elif echo "$notice" | grep -q 'base_file=%2F%2Fraw.githubusercontent.com'; then
elif printf '%s' "$REVIEW_URL" | grep -q 'base_file=%2F%2Fraw.githubusercontent.com'; then
echo "FAIL: 'https:' was stripped from base, the strip_ref_prefix URL guard is missing" >&2
echo "notice line: $notice" >&2
exit 1
else
echo "FAIL: base_file= param did not contain the raw.githubusercontent.com host as expected" >&2
echo "notice line: $notice" >&2
echo "FAIL: base_file= did not contain the raw.githubusercontent.com host as expected" >&2
exit 1
fi

changelog_free_review_url_strips_git_ref_prefix:
runs-on: ubuntu-latest
name: "Test changelog free review URL strips origin/main: prefix from git-ref base"
# Companion: git-ref base must have its prefix stripped to a bare path.
name: "Test changelog free review URL strips the ref: prefix from a git-ref base"
# Companion to the preserve test: a git-ref base (HEAD:specs/base.yaml) must
# have its ref prefix stripped so base_file is just the path. Also exercises
# real git-ref resolution, the action's recommended base form.
steps:
- uses: actions/checkout@v6
- name: Stub oasdiff to report a change so the notice fires
- uses: ./changelog
id: clog
with:
base: 'HEAD:specs/base.yaml'
revision: 'specs/revision-breaking.yaml'
- name: Assert the git-ref prefix is stripped from base_file
env:
REVIEW_URL: ${{ steps.clog.outputs.review_url }}
run: |
set -euo pipefail
mkdir -p /tmp/stub
cat > /tmp/stub/oasdiff <<'STUB'
#!/bin/sh
echo '1 change(s)'
STUB
chmod +x /tmp/stub/oasdiff

mkdir -p /tmp/run
export GITHUB_REPOSITORY=foo/bar
export GITHUB_SHA=deadbeef
export GITHUB_BASE_REF=main
export GITHUB_OUTPUT=/tmp/run/github-output
export GITHUB_STEP_SUMMARY=/tmp/run/step-summary
cat > /tmp/run/event.json <<EVT
{"pull_request":{"head":{"sha":"deadbeef"},"base":{"sha":"baadcafe"}}}
EVT
export GITHUB_EVENT_PATH=/tmp/run/event.json

export PATH=/tmp/stub:$PATH
# Invoke with bash (see the companion job): dash on the runner rejects
# the entrypoint's `set -o pipefail`.
out=$(bash ./changelog/entrypoint.sh \
'origin/main:multi-file/openapi.yaml' 'HEAD:multi-file/openapi.yaml' \
'' '' '' '' '' '' '' '' '' '' '' '' 2>&1)
echo "--- entrypoint output ---"
echo "$out"

if ! echo "$out" | grep -q "::notice::.*API changes"; then
echo "FAIL: review-URL notice line missing" >&2
echo "review_url=$REVIEW_URL"
if [ -z "$REVIEW_URL" ]; then
echo "FAIL: review_url output is empty (expected changes to fire the notice)" >&2
exit 1
fi
notice=$(echo "$out" | grep "::notice::.*API changes")
if echo "$notice" | grep -q 'base_file=multi-file%2Fopenapi.yaml'; then
echo "PASS: origin/main: prefix stripped from base"
if printf '%s' "$REVIEW_URL" | grep -q 'base_file=specs%2Fbase.yaml'; then
echo "PASS: ref prefix stripped from base"
else
echo "FAIL: base_file= did not have the git-ref prefix stripped" >&2
echo "notice line: $notice" >&2
echo "FAIL: base_file= did not have the git-ref prefix stripped (got: $REVIEW_URL)" >&2
exit 1
fi

2 changes: 2 additions & 0 deletions breaking/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ inputs:
outputs:
breaking:
description: 'Output summary of API breaking changes, encompassing both warnings and errors'
review_url:
description: 'URL of the free oasdiff review page for these changes (empty when there are no breaking changes)'
runs:
using: 'docker'
image: 'Dockerfile'
Expand Down
23 changes: 13 additions & 10 deletions breaking/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,22 @@ readonly warn_ignore="${13}"
readonly output_to_file="${14}"

write_output () {
_write_output_output="$1"
local output="$1"
if [ -n "$output_to_file" ]; then
_write_output_file_output="$2"
if [ -z "$_write_output_file_output" ]; then
_write_output_file_output=$_write_output_output

local file_output="$2"
if [ -z "$file_output" ]; then
file_output=$output
fi
echo "$_write_output_file_output" >> "$output_to_file"
echo "$file_output" >> "$output_to_file"
fi
# github-action limits output to 1MB
# we count bytes because unicode has multibyte characters
size=$(echo "$_write_output_output" | wc -c)
size=$(echo "$output" | wc -c)
if [ "$size" -ge "1000000" ]; then
echo "WARN: diff exceeds the 1MB limit, truncating output..." >&2
_write_output_output=$(echo "$_write_output_output" | head -c 1000000)
output=$(echo "$output" | head -c 1000000)
fi
echo "$_write_output_output" >>"$GITHUB_OUTPUT"
echo "$output" >>"$GITHUB_OUTPUT"
}

echo "running oasdiff breaking... base: $base, revision: $revision, fail_on: $fail_on, include_checks: $include_checks, include_path_params: $include_path_params, deprecation_days_beta: $deprecation_days_beta, deprecation_days_stable: $deprecation_days_stable, exclude_elements: $exclude_elements, filter_extension: $filter_extension, composed: $composed, flatten_allof: $flatten_allof, err_ignore: $err_ignore, warn_ignore: $warn_ignore, output_to_file: $output_to_file"
Expand Down Expand Up @@ -127,7 +126,7 @@ if [ -n "$breaking_changes" ] && ! echo "$breaking_changes" | head -n 1 | grep -
if [ -z "$head_sha" ]; then head_sha="$GITHUB_SHA"; fi
# base_sha must be an immutable commit SHA, not the branch name. Using
# $GITHUB_BASE_REF (the branch) makes the URL decay whenever the branch
# advances past the file's commit e.g. someone merges a rename of the
# advances past the file's commit, e.g. someone merges a rename of the
# spec file and every previously-emitted /review URL starts 404'ing
# because raw.githubusercontent.com now resolves the branch to a newer
# commit where the file lives at a different path.
Expand All @@ -141,5 +140,9 @@ else
fi

echo "$delimiter" >>"$GITHUB_OUTPUT"
# review_url is a single-line output, written after the multiline `breaking`
# block is closed so it doesn't get folded into that value. Empty when there
# are no breaking changes (the notice/URL only fire then).
echo "review_url=${free_review_url:-}" >> "$GITHUB_OUTPUT"

exit $exit_code
2 changes: 2 additions & 0 deletions changelog/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ inputs:
outputs:
changelog:
description: 'Output summary of API changelog'
review_url:
description: 'URL of the free oasdiff review page for these changes (empty when there are no changes)'
runs:
using: 'docker'
image: 'Dockerfile'
Expand Down
12 changes: 8 additions & 4 deletions changelog/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ if [ -n "$level" ]; then
fi
echo "flags: $flags"

set -o pipefail

# *** github action step output ***

# output name should be in the syntax of multiple lines:
Expand Down Expand Up @@ -119,8 +117,10 @@ if [ -n "$output" ] && ! echo "$output" | head -n 1 | grep -q "^No "; then
if [ -z "$head_sha" ]; then head_sha="$GITHUB_SHA"; fi
# base_sha must be an immutable commit SHA, not the branch name. Using
# $GITHUB_BASE_REF (the branch) makes the URL decay whenever the branch
# advances past the file's commit. See breaking/entrypoint.sh for the
# full rationale.
# advances past the file's commit, e.g. someone merges a rename of the
# spec file and every previously-emitted /review URL starts 404'ing
# because raw.githubusercontent.com now resolves the branch to a newer
# commit where the file lives at a different path.
base_sha=$(jq -r '.pull_request.base.sha // empty' "$GITHUB_EVENT_PATH" 2>/dev/null || echo "")
if [ -z "$base_sha" ]; then base_sha=$(git rev-parse "origin/$GITHUB_BASE_REF" 2>/dev/null || echo "$GITHUB_BASE_REF"); fi
free_review_url="https://www.oasdiff.com/review?owner=${owner}&repo=${repo}&base_sha=$(urlencode "$base_sha")&rev_sha=${head_sha}&base_file=$(urlencode "$base_path")&rev_file=$(urlencode "$rev_path")"
Expand All @@ -131,6 +131,10 @@ else
fi

echo "$delimiter" >>"$GITHUB_OUTPUT"
# review_url is a single-line output, written after the multiline `changelog`
# block is closed so it doesn't get folded into that value. Empty when there
# are no changes (the notice/URL only fire then).
echo "review_url=${free_review_url:-}" >> "$GITHUB_OUTPUT"

# *** github action step output ***

2 changes: 0 additions & 2 deletions diff/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ echo "flags: $flags"
delimiter=$(cat /proc/sys/kernel/random/uuid | tr -d '-')
echo "diff<<$delimiter" >>"$GITHUB_OUTPUT"

set -o pipefail

# Capture the exit code from oasdiff command while still getting the output
exit_code=0
if [ -n "$flags" ]; then
Expand Down
Loading