Skip to content
Draft
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
143 changes: 141 additions & 2 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ name: Java CI with Gradle
on:
push:
pull_request:
workflow_dispatch:

env:
SVCOMP_REFERENCE_URL: https://zenodo.org/api/records/17748741/files/swat-verify.zip/content
SVCOMP_REFERENCE_MD5: 8c776d19ac33ecf5c1c7441d16cc18a6
Comment on lines +9 to +10

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@k0lja Can you propose a different mechanism, perhaps another repository here that publishes the required files, I dont want to reference zenodo here in the CI

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In addition, the venv we are using is built on the specific ubuntu version required by sv-comp. updating the dependencies is a hassle atm. Can you check if it could be possible either here or in the supporting repo (for the above) you can actually build the venv based on the requirements (pip freeze the current venv) as part of the ci there? this would make updating the venv much easier


jobs:
build:
Expand All @@ -18,8 +23,142 @@ jobs:
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you are at it, could you also check why the setup-gradle v4 is referenced using this hash I assume? is that the proper way to do that? (I know this is older then your changes but I was wondering for some time)

- name: Prepare Solver Dependencies
run: ./gradlew copyNativeLibs
- name: Build
run: ./gradlew build -x test
run: ./gradlew --no-daemon build -x test
- name: Build WitnessCreator JAR
run: ./gradlew --no-daemon :targets:sv-comp:WitnessCreator:shadowJar
Comment on lines +30 to +31

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed could you also move the full witness creator into its own repo that publishes an artifact we can use here?

- name: Upload JARs
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: release-jars-${{ github.sha }}
path: |
symbolic-executor/lib/symbolic-executor.jar
targets/sv-comp/WitnessCreator/build/libs/WitnessCreator.jar
if-no-files-found: error
retention-days: 1

package:
needs: build
if: >-
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'push' && (
github.ref == 'refs/heads/main' ||
github.ref == 'refs/heads/dev' ||
startsWith(github.ref, 'refs/tags/')
))
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v5
- name: Download JARs
uses: actions/download-artifact@v4
with:
name: release-jars-${{ github.sha }}
path: ${{ runner.temp }}/release-jars
- name: Determine release channel
id: meta
run: |
ref_type="${GITHUB_REF_TYPE}"
ref_name="${GITHUB_REF_NAME}"
sha_short="${GITHUB_SHA::7}"

channel="" # release/tag name; empty -> build artifact only, no release
release="false"
rolling="false" # rolling channels move their tag to the current commit
prerelease="false"

if [[ "$ref_type" == "tag" ]]; then
channel="$ref_name"
release="true"
elif [[ "$ref_name" == "main" ]]; then
channel="latest"
release="true"
rolling="true"
elif [[ "$ref_name" == "dev" ]]; then
channel="latest-dev"
release="true"
rolling="true"
prerelease="true"
fi

# Channel-stable asset name gives the nightly cron a fixed download URL;
# the exact commit is recorded in the release notes and BUILD_INFO.txt.
if [[ -n "$channel" ]]; then
version="$channel"
else
version="$sha_short"
fi
zip_name="swat-svcomp-${version}.zip"

{
echo "channel=${channel}"
echo "version=${version}"
echo "zip-name=${zip_name}"
echo "release=${release}"
echo "rolling=${rolling}"
echo "prerelease=${prerelease}"
} >> "${GITHUB_OUTPUT}"
- name: Download SV-COMP reference runtime
run: |
curl --fail --location --retry 3 --output "${RUNNER_TEMP}/swat-verify.zip" "${SVCOMP_REFERENCE_URL}"
echo "${SVCOMP_REFERENCE_MD5} ${RUNNER_TEMP}/swat-verify.zip" | md5sum --check -
unzip -q "${RUNNER_TEMP}/swat-verify.zip" -d "${RUNNER_TEMP}/swat-reference"
- name: Pack SV-COMP ZIP
env:
SWAT_SVCOMP_VERSION: ${{ steps.meta.outputs.version }}
SWAT_SVCOMP_ARTIFACT_DIR: ${{ runner.temp }}/release-jars
SWAT_SVCOMP_REFERENCE_DIR: ${{ runner.temp }}/swat-reference/swat-verify
SWAT_SVCOMP_COMMIT: ${{ github.sha }}
SWAT_SVCOMP_REF: ${{ github.ref_name }}
SWAT_SVCOMP_CHANNEL: ${{ steps.meta.outputs.channel }}
run: scripts/package-svcomp.sh
- name: Upload SV-COMP ZIP artifact
uses: actions/upload-artifact@v4
with:
name: swat-svcomp-${{ steps.meta.outputs.version }}
path: build/distributions/${{ steps.meta.outputs.zip-name }}
if-no-files-found: error
- name: Publish release
if: steps.meta.outputs.release == 'true'
env:
GH_TOKEN: ${{ github.token }}
CHANNEL: ${{ steps.meta.outputs.channel }}
ZIP_NAME: ${{ steps.meta.outputs.zip-name }}
ROLLING: ${{ steps.meta.outputs.rolling }}
PRERELEASE: ${{ steps.meta.outputs.prerelease }}
run: |
zip_path="build/distributions/${ZIP_NAME}"
notes="$(printf 'Automated SWAT SV-COMP package.\n\nRef: %s\nCommit: %s\nRun: %s/%s/actions/runs/%s\n' \
"$GITHUB_REF_NAME" "$GITHUB_SHA" "$GITHUB_SERVER_URL" "$GITHUB_REPOSITORY" "$GITHUB_RUN_ID")"

prerelease_flag=()
[[ "$PRERELEASE" == "true" ]] && prerelease_flag=(--prerelease)

if [[ "$ROLLING" == "true" ]]; then
# Refresh the rolling channel: drop the old release + tag, then recreate
# it at the current commit so the tag always tracks the channel head.
# Uses the default GITHUB_TOKEN, so the new tag does not retrigger CI.
gh release delete "$CHANNEL" --yes --cleanup-tag 2>/dev/null || true
gh release create "$CHANNEL" "$zip_path" \
--target "$GITHUB_SHA" \
--title "SWAT ${CHANNEL} (${GITHUB_SHA::7})" \
--notes "$notes" \
"${prerelease_flag[@]}"
else
# Permanent, version-tagged release (the tag already points at this commit).
if gh release view "$CHANNEL" >/dev/null 2>&1; then
gh release upload "$CHANNEL" "$zip_path" --clobber
else
gh release create "$CHANNEL" "$zip_path" \
--title "SWAT ${CHANNEL}" \
--notes "$notes" \
"${prerelease_flag[@]}"
fi
fi

test:
needs: build
Expand Down Expand Up @@ -82,4 +221,4 @@ jobs:
java-version: '17'
distribution: 'temurin'
- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4
uses: gradle/actions/dependency-submission@017a9effdb900e5b5b2fddfb590a105619dca3c3 # v4
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ targets/applications/openolat/libs/z3/
**/logs/
**/logs-debug/
**/results/
**/runs/
**/runs-debug/
**/*.class
/build/
**/build/
Expand Down
180 changes: 180 additions & 0 deletions scripts/package-svcomp.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#!/usr/bin/env bash
set -euo pipefail

# This script packages artifacts that were already produced by CI. It must not
# invoke Gradle, create virtual environments, or download dependencies.
#
# Generated files are expected in the repository checkout after the CI build.
# Set SWAT_SVCOMP_ARTIFACT_DIR only if those generated files live somewhere
# else. The artifact root must contain:
#
# - symbolic-executor/lib/symbolic-executor.jar
# - targets/sv-comp/WitnessCreator/build/libs/WitnessCreator.jar
#
# Set SWAT_SVCOMP_REFERENCE_DIR to the extracted Zenodo reference package root
# from https://zenodo.org/records/17748741. The reference root is used for the
# pinned SV-COMP Python environment and JavaSMT compatibility JAR:
#
# - .venv_ubuntu_24_04_1__x86_64/
#
# Z3 is taken from the vendored Linux distribution ZIP in this repository.
#
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"

VERSION="${SWAT_SVCOMP_VERSION:-$(git rev-parse --short HEAD)}"
COMMIT="${SWAT_SVCOMP_COMMIT:-$(git rev-parse HEAD 2>/dev/null || echo unknown)}"
REF="${SWAT_SVCOMP_REF:-$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo unknown)}"
CHANNEL="${SWAT_SVCOMP_CHANNEL:-}"
PACKAGE_NAME="swat-svcomp-${VERSION}"
WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/swat-svcomp-package.XXXXXX")"
PACKAGE_DIR="${WORK_DIR}/${PACKAGE_NAME}"
DIST_DIR="${ROOT_DIR}/build/distributions"
SUPPORT_DIR="${ROOT_DIR}/scripts/svcomp-package"
ARTIFACT_DIR="$(cd "${SWAT_SVCOMP_ARTIFACT_DIR:-$ROOT_DIR}" && pwd)"
REFERENCE_DIR="${SWAT_SVCOMP_REFERENCE_DIR:-}"
VENV_DIR_NAME="${SWAT_SVCOMP_VENV_DIR_NAME:-.venv_ubuntu_24_04_1__x86_64}"
LINUX_Z3_DIST="z3-4.15.4-x64-glibc-2.39"
LINUX_Z3_ZIP="${ROOT_DIR}/libs/${LINUX_Z3_DIST}.zip"

if [[ -n "$REFERENCE_DIR" ]]; then
REFERENCE_DIR="$(cd "$REFERENCE_DIR" && pwd)"
fi

fail() {
echo "error: $*" >&2
exit 1
}

artifact_file() {
local rel="$1"
local path="${ARTIFACT_DIR}/${rel}"
[[ -f "$path" ]] || fail "missing built artifact file: ${path}"
printf '%s\n' "$path"
}

reference_file() {
local rel="$1"
[[ -n "$REFERENCE_DIR" ]] || fail "SWAT_SVCOMP_REFERENCE_DIR is required for ${rel}"

local path="${REFERENCE_DIR}/${rel}"
[[ -f "$path" ]] || fail "missing Zenodo reference file: ${path}"
printf '%s\n' "$path"
}

first_artifact_file() {
local path
for rel in "$@"; do
path="${ARTIFACT_DIR}/${rel}"
if [[ -f "$path" ]]; then
printf '%s\n' "$path"
return 0
fi
done
fail "missing built artifact file; checked: $*"
}

copy_tree_files() {
local src="$1"
local dest="$2"
mkdir -p "$dest"
find "$src" -type f \
! -path '*/__pycache__/*' \
! -path '*/.venv/*' \
! -name '*.pyc' \
! -name '*.pyo' \
! -name '*.iml' \
-print0 | while IFS= read -r -d '' file; do
local rel="${file#"$src"/}"
mkdir -p "$dest/$(dirname "$rel")"
cp "$file" "$dest/$rel"
done
}

copy_artifact_file() {
local src="$1"
local dest="$2"
local mode="${3:-0644}"
mkdir -p "$(dirname "$dest")"
install -m "$mode" "$src" "$dest"
}

copy_artifact_tree() {
local src="$1"
local dest="$2"
[[ -d "$src" ]] || fail "missing artifact directory: ${src}"
mkdir -p "$(dirname "$dest")"
cp -a "$src" "$dest"
}

install_z3_runtime_file() {
local name="$1"
local mode="${2:-0644}"
local dest="${PACKAGE_DIR}/libs/java-library-path/${name}"

[[ -f "$LINUX_Z3_ZIP" ]] || fail "missing vendored Linux Z3 distribution: ${LINUX_Z3_ZIP}"
mkdir -p "$(dirname "$dest")"
unzip -p "$LINUX_Z3_ZIP" "${LINUX_Z3_DIST}/bin/${name}" > "$dest"
chmod "$mode" "$dest"
}

echo "Packaging repository files from: ${ROOT_DIR}"
echo "Packaging built artifacts from: ${ARTIFACT_DIR}"

echo "Creating package staging directory: ${PACKAGE_DIR}"
mkdir -p "$PACKAGE_DIR"
{
echo "version=${VERSION}"
echo "channel=${CHANNEL}"
echo "ref=${REF}"
echo "commit=${COMMIT}"
} > "$PACKAGE_DIR/BUILD_INFO.txt"

install -m 0644 LICENSE "$PACKAGE_DIR/LICENSE"
install -m 0644 Third-Party-Licenses.html "$PACKAGE_DIR/Third-Party-Licenses.html"
install -m 0644 "$SUPPORT_DIR/README.md" "$PACKAGE_DIR/README.md"
install -m 0755 "$SUPPORT_DIR/run-swat.sh" "$PACKAGE_DIR/run-swat.sh"
install -m 0755 "$SUPPORT_DIR/compile-target.sh" "$PACKAGE_DIR/compile-target.sh"
install -m 0755 "$SUPPORT_DIR/smoketest.sh" "$PACKAGE_DIR/smoketest.sh"
install -m 0755 "$SUPPORT_DIR/run_swat.py" "$PACKAGE_DIR/run_swat.py"
install -m 0644 targets/sv-comp/sv-comp.cfg "$PACKAGE_DIR/sv-comp.cfg"

EXECUTOR_JAR="$(first_artifact_file \
symbolic-executor/lib/symbolic-executor.jar \
symbolic-executor/build/libs/symbolic-executor-all.jar)"
copy_artifact_file "$EXECUTOR_JAR" "$PACKAGE_DIR/symbolic-executor/lib/symbolic-executor.jar"

copy_tree_files symbolic-explorer "$PACKAGE_DIR/symbolic-explorer"

WITNESS_CREATOR_JAR="$(artifact_file targets/sv-comp/WitnessCreator/build/libs/WitnessCreator.jar)"
copy_artifact_file "$WITNESS_CREATOR_JAR" "$PACKAGE_DIR/WitnessCreator/build/libs/WitnessCreator.jar"
mkdir -p "$PACKAGE_DIR/WitnessCreator/witnesses"
install -m 0644 targets/sv-comp/WitnessCreator/witnesses/default_violation.st "$PACKAGE_DIR/WitnessCreator/witnesses/default_violation.st"
install -m 0644 targets/sv-comp/WitnessCreator/witnesses/witness.st "$PACKAGE_DIR/WitnessCreator/witnesses/witness.st"

install_z3_runtime_file z3 0755
install_z3_runtime_file libz3.so
install_z3_runtime_file libz3java.so
install_z3_runtime_file com.microsoft.z3.jar
install_z3_runtime_file libz3.a
JAVA_SMT_JAR="$(reference_file libs/java-library-path/java-smt-latest.jar)"
copy_artifact_file "$JAVA_SMT_JAR" "$PACKAGE_DIR/libs/java-library-path/java-smt-latest.jar"

copy_tree_files "$SUPPORT_DIR/smoketest" "$PACKAGE_DIR/smoketest"

[[ -n "$REFERENCE_DIR" ]] || fail "SWAT_SVCOMP_REFERENCE_DIR must point to the extracted Zenodo package root for ${VENV_DIR_NAME}"
copy_artifact_tree "${REFERENCE_DIR}/${VENV_DIR_NAME}" "${PACKAGE_DIR}/${VENV_DIR_NAME}"

mkdir -p "$DIST_DIR"
ZIP_PATH="${DIST_DIR}/${PACKAGE_NAME}.zip"
ZIP_TMP="${WORK_DIR}/${PACKAGE_NAME}.zip"

echo "Creating ZIP: ${ZIP_PATH}"
(
cd "$WORK_DIR"
zip -qr "$ZIP_TMP" "$PACKAGE_NAME"
)
cp "$ZIP_TMP" "$ZIP_PATH"

echo "Package created at: ${ZIP_PATH}"
echo "Staging directory left at: ${PACKAGE_DIR}"
19 changes: 19 additions & 0 deletions scripts/svcomp-package/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SWAT SV-COMP Package

This archive contains a runnable SWAT package for SV-COMP style Java verification tasks.

Important entry points:

- `run-swat.sh`: verifier entry point used by BenchExec.
- `compile-target.sh`: helper used by `run_swat.py` to compile Java benchmark sources.
- `smoketest.sh`: runs SWAT on two bundled smoke-test targets.
- `sv-comp.cfg`: SWAT configuration for SV-COMP mode.

The package expects Java 17 and the bundled `.venv_ubuntu_24_04_1__x86_64`
Python environment. `run-swat.sh` intentionally uses only that environment.

Example:

```sh
./run-swat.sh ../../sv-benchmarks/java/properties/valid-assert.prp smoketest/common smoketest
```
Loading
Loading