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
37 changes: 37 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,43 @@ concurrency:
cancel-in-progress: true

jobs:
repository-policy:
name: Repository policy
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up repository linters
uses: jdx/mise-action@9e7f7633ff6f6d6048a9418a68d48f288f50eb14 # v4.2.3
with:
install_args: actionlint zizmor

- name: Lint GitHub Actions
run: |
actionlint -color
zizmor --min-severity medium .github/workflows

consumer-isolation:
name: Consumer dependency isolation
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Set up Java
uses: actions/setup-java@03ad4de0992f5dab5e18fcb136590ce7c4a0ac95 # v5
with:
distribution: temurin
java-version: '21'

- name: Verify isolated consumer
run: ./scripts/verify-consumer-isolation.sh

build:
name: Build (Java ${{ matrix.java }})
runs-on: ${{ matrix.os }}
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install mdbook-lint
shell: bash
Expand Down Expand Up @@ -65,6 +67,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Check external links
uses: lycheeverse/lychee-action@e7477775783ea5526144ba13e8db5eec57747ce8 # v2.9.0
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ The format is based on [Keep a Changelog], and this project adheres to [Semantic
- Documentation checks based on `mdbook-lint` and Lychee.
- Consumer-classpath verification for applications that install a single DATEX II model.
- Adversarial XML tests covering DTDs, external entities, and recursive entity expansion.
- A single contributor verification command with isolated Maven consumer checks, actionable
failure logs, coverage summaries, and GitHub Actions linting.

### Changed

Expand Down
7 changes: 6 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ Maven wrapper pins Maven.

```bash
mise install
./mvnw verify
./scripts/verify.sh
```

The verification script checks GitHub Actions syntax and security, verifies the critical XML and
validation modules, tests the consumer dependency graph with an isolated Maven repository, runs
the complete Maven reactor, and prints the final coverage ratios. Its full log is written to
`target/verification/verify.log`.

Read the [architecture guide](docs/architecture.md) before changing module boundaries or adding a
dependency.

Expand Down
6 changes: 4 additions & 2 deletions mise.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Developer toolchain pinned for reproducible local and CI builds.
# Maven is provided by the committed Maven Wrapper (./mvnw), so only Java is pinned here.
# Run `mise install` to provision Java, then `./mvnw verify`.
# Maven is provided by the committed Maven Wrapper (./mvnw).
# Run `mise install`, then `./scripts/verify.sh`.
[tools]
java = "temurin-21.0.11+10.0.LTS"
actionlint = "1.7.12"
zizmor = "1.28.0"
46 changes: 46 additions & 0 deletions scripts/verify-consumer-isolation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail

project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
temporary_root="$(mktemp -d "${TMPDIR:-/tmp}/datex4j-consumer-isolation.XXXXXX")"
local_repository="${temporary_root}/repository"
dependency_tree="${temporary_root}/dependency-tree.txt"

cleanup() {
rm -rf "${temporary_root}"
}
trap cleanup EXIT

cd "${project_root}"

./mvnw --batch-mode --no-transfer-progress \
-Dmaven.repo.local="${local_repository}" \
-DskipTests \
-Djacoco.skip=true \
-pl datex4j-xml,datex4j-json,datex4j-model-v3_7 \
-am \
install

./mvnw --batch-mode --no-transfer-progress \
-Dmaven.repo.local="${local_repository}" \
-f datex4j-consumer-tests/pom.xml \
-Dscope=test \
-DoutputType=text \
-DoutputFile="${dependency_tree}" \
dependency:tree

if ! grep -Eq 'dev\.juherr\.datex4j:datex4j-model-v3_7:' "${dependency_tree}"; then
echo "Expected datex4j-model-v3_7 is missing from the consumer dependency tree." >&2
exit 1
fi

if grep -Eq \
'dev\.juherr\.datex4j:(datex4j-model:|datex4j-model-v(2_[0-3]|3_[0-6]):)' \
"${dependency_tree}"; then
echo "Unexpected generated model dependency found:" >&2
grep -E 'dev\.juherr\.datex4j:(datex4j-model:|datex4j-model-v[23]_)' \
"${dependency_tree}" >&2
exit 1
fi

echo "Consumer isolation verified: only datex4j-model-v3_7 is installed."
61 changes: 61 additions & 0 deletions scripts/verify.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail

project_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
report_directory="${project_root}/target/verification"
log_file="${report_directory}/verify.log"

mkdir -p "${report_directory}"
: >"${log_file}"

run_logged() {
local description="$1"
shift
echo "==> ${description}" | tee -a "${log_file}"
if "$@" 2>&1 | tee -a "${log_file}"; then
return
fi
echo "Verification failed during: ${description}" >&2
echo "Last 80 log lines:" >&2
tail -n 80 "${log_file}" >&2
exit 1
}

print_coverage() {
local module="$1"
local report="${project_root}/${module}/target/site/jacoco/jacoco.csv"
if [[ ! -f "${report}" ]]; then
echo "${module}: no JaCoCo report"
return
fi
awk -F, -v module="${module}" \
'NR > 1 { missed += $8; covered += $9 }
END {
total = missed + covered;
if (total == 0) {
printf "%s line coverage: 0/0 (0.0%%)\n", module;
exit;
}
printf "%s line coverage: %d/%d (%.1f%%)\n", module, covered, total, 100 * covered / total
}' \
"${report}"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

cd "${project_root}"

run_logged "GitHub Actions syntax" mise exec -- actionlint -color
run_logged \
"GitHub Actions security" \
mise exec -- zizmor --min-severity medium .github/workflows
run_logged \
"critical XML and validation modules" \
./mvnw --batch-mode --no-transfer-progress \
-pl datex4j-xml,datex4j-validation -am verify
run_logged "isolated consumer dependency graph" ./scripts/verify-consumer-isolation.sh
run_logged \
"full Maven reactor" \
./mvnw --batch-mode --no-transfer-progress verify

print_coverage datex4j-xml | tee -a "${log_file}"
print_coverage datex4j-validation | tee -a "${log_file}"
echo "Verification succeeded. Full log: ${log_file}"
Loading