Skip to content

Nightly

Nightly #6

Workflow file for this run

name: Nightly
# build.yml runs on push and pull_request, so it only tells you about changes
# made HERE. This repository's other moving part is outside it: the parser
# artifact published to https://www.sqlparser.com/maven/. A release there can
# change demo output or drop an API without a single commit landing in this
# repo, and nothing would notice until someone ran a demo by hand.
#
# So this workflow runs on a timer and covers both:
# pinned -- ${gsp.core.version} from pom.xml, the version the README
# documents, on the two JDKs the demos claim to support.
# latest -- whatever is newest on sqlparser.com right now. This is the job
# that earns the nightly. When it goes red and `pinned` stays
# green, a new parser release broke the demos.
#
# Both jobs do the same four things: prove no parser jar is committed, compile
# everything, run the whole test suite, and then actually run the demos --
# every one of them for launch, and a table of them with real arguments checked
# against expected output.
on:
schedule:
# 03:17 UTC. Not on the hour: GitHub drops scheduled runs when too many
# repositories ask for the same popular minute.
- cron: "17 3 * * *"
workflow_dispatch:
inputs:
parser_version:
description: "Parser version for the 'latest' job (blank = resolve newest from sqlparser.com)"
required: false
type: string
permissions:
contents: read
jobs:
pinned:
name: "pinned parser (JDK ${{ matrix.java }})"
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# The parser jar is Java 8 bytecode and the POM pins source/target 1.8.
java: ["8", "21"]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: ${{ matrix.java }}
cache: maven
# A vendored parser is what once let these demos compile against a build
# years older than their own source, so its absence is an invariant worth
# asserting rather than a convention worth documenting.
- name: No parser jar is committed
run: |
set -euo pipefail
if git ls-files | grep -E '(^|/)(gsqlparser|gudusoft\.gsqlparser)[^/]*\.jar$'; then
echo "::error::a parser jar is committed; it must be resolved from Gudu's Maven repository"
exit 1
fi
echo "ok: no parser jar in the index"
- name: Parser version is consistent across all POMs
run: .github/scripts/set-parser-version.sh --check
- name: Report the parser being used
run: |
set -euo pipefail
v=$(mvn -B -q help:evaluate -Dexpression=gsp.core.version -DforceStdout)
echo "pinned parser version: $v"
echo "### Pinned parser \`$v\` (JDK ${{ matrix.java }})" >> "$GITHUB_STEP_SUMMARY"
- name: Compile everything
run: mvn -B package -DskipTests
- name: Test
run: mvn -B test
- name: Check the results
run: .github/scripts/check-test-results.sh
# The standalone lineage tool, run rather than merely built. It was its own
# POM until 2026-07-28, and only ever compiled here, which is how it
# shipped a missing JAXB dependency (issue #47) and an unrunnable
# documented command (issue #46) through green builds.
- name: Run the standalone dlineage jar
run: .github/scripts/smoke-dlineage-jar.sh
- name: Every demo starts
run: .github/scripts/run-all-demos.sh --timeout 90
- name: Demos produce their expected output
run: .github/scripts/run-demo-cases.sh --timeout 180
latest:
name: "latest published parser"
runs-on: ubuntu-latest
# Needed only by the last step, which opens the bump PR. Everything above it
# is read-only.
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: maven
# <release> is the newest non-snapshot; fall back to <latest>, then to the
# last <version> listed. Failing to resolve is an error rather than a
# silent fallback to the pinned version: a job that quietly re-tests what
# `pinned` already covers looks green while testing nothing new.
- name: Resolve the newest published parser
id: ver
run: |
set -euo pipefail
if [ -n "${{ inputs.parser_version }}" ]; then
v="${{ inputs.parser_version }}"
echo "using the version supplied to workflow_dispatch: $v"
else
url=https://www.sqlparser.com/maven/com/gudusoft/gsqlparser/maven-metadata.xml
curl -sSf --retry 3 --retry-delay 5 -o meta.xml "$url"
v=$(sed -n 's:.*<release>\(.*\)</release>.*:\1:p' meta.xml | head -1)
[ -n "$v" ] || v=$(sed -n 's:.*<latest>\(.*\)</latest>.*:\1:p' meta.xml | head -1)
[ -n "$v" ] || v=$(sed -n 's:.*<version>\(.*\)</version>.*:\1:p' meta.xml | tail -1)
if [ -z "$v" ]; then
echo "::error::could not read a version out of $url"
cat meta.xml
exit 1
fi
fi
pinned=$(mvn -B -q help:evaluate -Dexpression=gsp.core.version -DforceStdout)
echo "version=$v" >> "$GITHUB_OUTPUT"
echo "newest published: $v / pinned in pom.xml: $pinned"
{
echo "### Latest published parser \`$v\`"
if [ "$v" = "$pinned" ]; then
echo "Same as the pinned version, so this job duplicates \`pinned\`."
else
echo "Pinned version is \`$pinned\`. If this job is red and \`pinned\` is green,"
echo "release \`$v\` broke the demos. If it is green, \`gsp.core.version\`"
echo "can be bumped to \`$v\`."
fi
} >> "$GITHUB_STEP_SUMMARY"
- name: Compile everything
run: mvn -B package -DskipTests -Dgsp.core.version=${{ steps.ver.outputs.version }}
- name: Test
run: mvn -B test -Dgsp.core.version=${{ steps.ver.outputs.version }}
- name: Check the results
run: .github/scripts/check-test-results.sh
# Same smoke run as the pinned job, against the jar "Compile everything"
# just built with -Dgsp.core.version=<newest release>. This is the check
# that would notice a new parser breaking data lineage at runtime while
# still compiling, which is precisely the failure mode a build-only step
# cannot see.
- name: Run the standalone dlineage jar against the newest release
run: .github/scripts/smoke-dlineage-jar.sh
- name: Every demo starts
env:
MVN_ARGS: -Dgsp.core.version=${{ steps.ver.outputs.version }}
run: .github/scripts/run-all-demos.sh --timeout 90
- name: Demos produce their expected output
env:
MVN_ARGS: -Dgsp.core.version=${{ steps.ver.outputs.version }}
run: .github/scripts/run-demo-cases.sh --timeout 180
# Everything above passed against this version, so the bump is already
# proven rather than proposed on faith: full suite, every demo started,
# and the demo cases checked against expected output. Opening a PR instead
# of committing keeps a human in the loop and gives the push-triggered
# build.yml a chance to disagree.
#
# Deliberately the LAST step in the job: any earlier failure means the new
# release broke something, and then no PR is what we want.
- name: Propose the bump when the newest release is green
if: github.ref == 'refs/heads/master'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NEW: ${{ steps.ver.outputs.version }}
run: |
set -euo pipefail
pinned=$(mvn -B -q help:evaluate -Dexpression=gsp.core.version -DforceStdout)
if [ "$NEW" = "$pinned" ]; then
echo "already on $NEW, nothing to propose"
exit 0
fi
branch="bump-parser-$NEW"
if gh pr list --head "$branch" --state open --json number \
--jq 'length' | grep -qv '^0$'; then
echo "a PR for $branch is already open"
exit 0
fi
if git ls-remote --exit-code --heads origin "$branch" >/dev/null 2>&1; then
echo "branch $branch already exists on origin; leaving it alone"
exit 0
fi
.github/scripts/set-parser-version.sh "$NEW"
.github/scripts/set-parser-version.sh --check
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git checkout -b "$branch"
git commit -aqm "Bump the parser from $pinned to $NEW
The nightly ran the newest published release through the same checks
the pinned version gets, and it passed all of them:
- full test suite, no failures
- every demo starts
- the demo cases in .github/scripts/demo-cases.tsv produce their
expected output
Opened automatically by .github/workflows/nightly.yml. Merge it if you
want the demos on $NEW; close it to stay on $pinned, and the nightly
will keep testing $NEW without asking again until a newer release
appears."
git push -q origin "$branch"
gh pr create --base master --head "$branch" \
--title "Bump the parser from $pinned to $NEW" \
--body "\`$NEW\` is the newest release on sqlparser.com. Tonight's nightly ran it through the same checks the pinned \`$pinned\` gets, and it passed all of them: the full test suite with no failures, every demo starting, and every case in \`.github/scripts/demo-cases.tsv\` producing its expected output.
This touches the four places the version is written -- \`pom.xml\` and the three \`connector/*/pom.xml\` -- via \`.github/scripts/set-parser-version.sh\`, so they cannot drift apart.
Merge to move the demos to \`$NEW\`. Close to stay on \`$pinned\`; the nightly will go on testing \`$NEW\` and will not reopen this until a newer release appears.
Opened by [\`nightly.yml\`](https://github.com/${{ github.repository }}/actions/workflows/nightly.yml)."
# The .bat family is the original Windows, no-Maven workflow. It went stale
# for years because nothing ran it; build.yml runs it per push and this runs
# it nightly, against a parser fetched fresh rather than a cached one.
windows-bat:
name: "Windows .bat scripts"
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "8"
cache: maven
- name: setenv.bat bootstraps the parser from Maven
shell: cmd
run: |
if exist external_lib\gsqlparser-*.jar (
echo ::error::a parser jar is committed to this repository; it must be fetched, not vendored
exit /b 1
)
call setenv\fetch-parser.bat
dir external_lib
for %%f in (external_lib\gsqlparser-*.jar) do exit /b 0
echo ::error::fetch-parser.bat produced no parser jar
exit /b 1
- name: Compile every demo via compile_*.bat
shell: cmd
run: |
setlocal enabledelayedexpansion
set FAILED=0
set COUNT=0
for /r "%GITHUB_WORKSPACE%\src\main\java" %%s in (compile_*.bat) do (
set /a COUNT+=1
pushd "%%~dps"
call "%%~nxs" < NUL > "%GITHUB_WORKSPACE%\c.txt" 2>&1
findstr /i /c:"error" /c:"file not found" /c:"no source files" "%GITHUB_WORKSPACE%\c.txt" >NUL && (
echo ::error::%%~nxs failed
type "%GITHUB_WORKSPACE%\c.txt"
set /a FAILED+=1
) || echo ok %%~nxs
popd
)
echo.
echo compiled !COUNT! demos, !FAILED! failed
rem An explicit exit is required: a trailing `if` whose condition is
rem false leaves whatever ERRORLEVEL the loop last set.
if !FAILED! GTR 0 exit /b 1
exit /b 0
- name: Launch every demo via run_*.bat
shell: cmd
run: |
setlocal enabledelayedexpansion
set FAILED=0
set COUNT=0
for /r "%GITHUB_WORKSPACE%\src\main\java" %%s in (run_*.bat) do (
set /a COUNT+=1
pushd "%%~dps"
call "%%~nxs" < NUL > "%GITHUB_WORKSPACE%\r.txt" 2>&1
findstr /c:"ClassNotFoundException" /c:"NoClassDefFoundError" /c:"Main method not found" "%GITHUB_WORKSPACE%\r.txt" >NUL && (
echo ::error::%%~nxs could not launch its class
type "%GITHUB_WORKSPACE%\r.txt"
set /a FAILED+=1
) || echo ok %%~nxs
popd
)
echo.
echo launched !COUNT! demos, !FAILED! failed
if !FAILED! GTR 0 exit /b 1
exit /b 0
- name: Run four demos with real arguments
shell: cmd
run: |
echo SELECT a.id FROM ta a; > "%GITHUB_WORKSPACE%\q.sql"
call :demo checksyntax checksyntax checksyntax "/f %GITHUB_WORKSPACE%\q.sql /t oracle" "syntax errors: 0" || exit /b 1
call :demo formatsql formatsql formatsql "%GITHUB_WORKSPACE%\q.sql" "SELECT" || exit /b 1
call :demo listGSPInfo listGSPInfo listGSPInfo "" "Supported DBs" || exit /b 1
call :demo modifysql modifysql replaceTablename "" "output sql" || exit /b 1
echo All .bat demos passed.
exit /b 0
:demo
setlocal
set DEMO=%~1
set CSCRIPT=%~2
set RSCRIPT=%~3
set ARGS=%~4
set EXPECT=%~5
echo.
echo ==== %DEMO% : compile_%CSCRIPT%.bat / run_%RSCRIPT%.bat ====
cd /d "%GITHUB_WORKSPACE%\src\main\java\gudusoft\gsqlparser\demos\%DEMO%"
call compile_%CSCRIPT%.bat < NUL > "%GITHUB_WORKSPACE%\c.txt" 2>&1
type "%GITHUB_WORKSPACE%\c.txt"
findstr /i /c:"error" "%GITHUB_WORKSPACE%\c.txt" >NUL && (
echo ::error::compile_%CSCRIPT%.bat reported an error
endlocal & exit /b 1
)
call run_%RSCRIPT%.bat %ARGS% < NUL > "%GITHUB_WORKSPACE%\r.txt" 2>&1
type "%GITHUB_WORKSPACE%\r.txt"
findstr /c:"%EXPECT%" "%GITHUB_WORKSPACE%\r.txt" >NUL || (
echo ::error::run_%RSCRIPT%.bat did not print "%EXPECT%"
endlocal & exit /b 1
)
endlocal & exit /b 0