@@ -50,12 +50,14 @@ jobs:
5050 outputs :
5151 baseline_solver_version : ${{ steps.step1.outputs.version }}
5252 needs_snapshot_built : ${{ steps.step1.outputs.needs_snapshot_built }}
53+ env :
54+ BASELINE : ${{ github.event.inputs.baseline }}
5355 steps :
5456 - name : Determine the baseline
5557 id : step1
5658 shell : bash
5759 run : |
58- if [[ "${{ github.event.inputs.baseline }} " =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
60+ if [[ "$BASELINE " =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]]; then
5961 VERSION="${BASH_REMATCH[1]}"
6062 NEEDS_SNAPSHOT_BUILT=false
6163 echo "Baseline is a release tag ($VERSION)."
7779 matrix :
7880 # When updating this list, use find-and-replace in the entire file to keep all such lists identical.
7981 example : [cloud_balancing, conference_scheduling, curriculum_course, examination, flow_shop, machine_reassignment, meeting_scheduling, nurse_rostering, patient_admission_scheduling, task_assigning, traveling_tournament, vehicle_routing]
80- env :
81- MVN_USERNAME : ' ${{ secrets.JFROG_ENTERPRISE_READ_ONLY_ACCESS_USERNAME }}'
82- MVN_PASSWORD : ' ${{ secrets.JFROG_ENTERPRISE_READ_ONLY_ACCESS_TOKEN }}'
8382 steps :
8483 - name : Checkout timefold-solver-benchmarks
8584 uses : actions/checkout@v6
9493 java-version : 25 # Always build with the least recent supported JDK.
9594 distribution : ' temurin'
9695 cache : ' maven'
97- server-id : ' timefold-solver-enterprise'
98- server-username : ' MVN_USERNAME'
99- server-password : ' MVN_PASSWORD'
10096
10197 # Only build the snapshots if determined by the decisions job.
10298 - name : Checkout timefold-solver
@@ -129,8 +125,9 @@ jobs:
129125 if : needs.decisions.outputs.needs_snapshot_built == 'true'
130126 working-directory : ./timefold-solver-benchmarks
131127 shell : bash
128+ env :
129+ TARGET_BRANCH : ${{ github.event.inputs.baseline }}
132130 run : |
133- TARGET_BRANCH="${{ github.event.inputs.baseline }}"
134131 if git ls-remote --exit-code --heads origin "$TARGET_BRANCH" > /dev/null; then
135132 git fetch --depth=1 origin "$TARGET_BRANCH"
136133 git checkout -B "$TARGET_BRANCH" FETCH_HEAD
@@ -139,8 +136,10 @@ jobs:
139136 - name : Compile the benchmark
140137 working-directory : ./timefold-solver-benchmarks
141138 shell : bash
139+ env :
140+ VERSION : ${{ needs.decisions.outputs.baseline_solver_version }}
142141 run : |
143- ./mvnw clean install -B -Dquickly -Dversion.ai.timefold.solver=${{ needs.decisions.outputs.baseline_solver_version }}
142+ ./mvnw clean install -B -Dquickly -Dversion.ai.timefold.solver=$VERSION
144143 mv target/benchmarks.jar ../benchmarks-baseline.jar
145144
146145 - name : Upload the binaries
@@ -158,9 +157,6 @@ jobs:
158157 matrix :
159158 # When updating this list, use find-and-replace in the entire file to keep all such lists identical.
160159 example : [cloud_balancing, conference_scheduling, curriculum_course, examination, flow_shop, machine_reassignment, meeting_scheduling, nurse_rostering, patient_admission_scheduling, task_assigning, traveling_tournament, vehicle_routing]
161- env :
162- MVN_USERNAME : ' ${{ secrets.JFROG_ENTERPRISE_READ_ONLY_ACCESS_USERNAME }}'
163- MVN_PASSWORD : ' ${{ secrets.JFROG_ENTERPRISE_READ_ONLY_ACCESS_TOKEN }}'
164160 steps :
165161 - name : Checkout timefold-solver-benchmarks
166162 uses : actions/checkout@v6
@@ -175,9 +171,6 @@ jobs:
175171 java-version : 25 # Always build with the least recent supported JDK.
176172 distribution : ' temurin'
177173 cache : ' maven'
178- server-id : ' timefold-solver-enterprise'
179- server-username : ' MVN_USERNAME'
180- server-password : ' MVN_PASSWORD'
181174
182175 - name : Checkout timefold-solver
183176 uses : actions/checkout@v6
@@ -201,8 +194,9 @@ jobs:
201194 - name : Switch to correct Enterprise branch if it exists
202195 working-directory : ./timefold-solver-enterprise
203196 shell : bash
197+ env :
198+ TARGET_BRANCH : ${{ github.event.inputs.branch }}
204199 run : |
205- TARGET_BRANCH="${{ github.event.inputs.branch }}"
206200 if git ls-remote --exit-code --heads origin "$TARGET_BRANCH" > /dev/null; then
207201 git fetch --depth=1 origin "$TARGET_BRANCH"
208202 git checkout -B "$TARGET_BRANCH" FETCH_HEAD
@@ -218,8 +212,9 @@ jobs:
218212 - name : Switch to correct Benchmarks branch if it exists
219213 working-directory : ./timefold-solver-benchmarks
220214 shell : bash
215+ env :
216+ TARGET_BRANCH : ${{ github.event.inputs.branch }}
221217 run : |
222- TARGET_BRANCH="${{ github.event.inputs.branch }}"
223218 if git ls-remote --exit-code --heads origin "$TARGET_BRANCH" > /dev/null; then
224219 git fetch --depth=1 origin "$TARGET_BRANCH"
225220 git checkout -B "$TARGET_BRANCH" FETCH_HEAD
@@ -251,14 +246,22 @@ jobs:
251246 steps :
252247 - name : Clean results of previous runs
253248 shell : bash
249+ env :
250+ BASELINE : ${{ github.event.inputs.baseline }}
251+ BRANCH : ${{ github.event.inputs.branch }}
254252 run : |
255253 rm -rf timefold-solver-benchmarks
256254 # GitHub expressions can't do this, so we need to hack this in shell.
257255 # DIRs are different, so that we can run "main" against "main" and have separate results.
258- echo "SANITIZED_BASELINE=$(echo "${{ github.event.inputs.baseline }}" | sed 's/\//\-/g')" >> $GITHUB_ENV
259- echo "BASELINE_DIR=baseline_$(echo "${{ github.event.inputs.baseline }}" | sed 's/\//\-/g')" >> $GITHUB_ENV
260- echo "SANITIZED_BRANCH=$(echo "${{ github.event.inputs.branch }}" | sed 's/\//\-/g')" >> $GITHUB_ENV
261- echo "SUT_DIR=sut_$(echo "${{ github.event.inputs.branch }}" | sed 's/\//\-/g')" >> $GITHUB_ENV
256+ # Strip CR/LF from inputs before writing to $GITHUB_ENV to prevent env-file injection.
257+ SANITIZED_BASELINE=$(echo "$BASELINE" | tr -d '\r\n' | sed 's/\//\-/g')
258+ SANITIZED_BRANCH=$(echo "$BRANCH" | tr -d '\r\n' | sed 's/\//\-/g')
259+ {
260+ echo "SANITIZED_BASELINE=$SANITIZED_BASELINE"
261+ echo "BASELINE_DIR=baseline_$SANITIZED_BASELINE"
262+ echo "SANITIZED_BRANCH=$SANITIZED_BRANCH"
263+ echo "SUT_DIR=sut_$SANITIZED_BRANCH"
264+ } >> "$GITHUB_ENV"
262265
263266 - name : Checkout timefold-solver-benchmarks
264267 uses : actions/checkout@v6
@@ -270,13 +273,15 @@ jobs:
270273 - name : Configure the benchmark
271274 working-directory : ./timefold-solver-benchmarks
272275 shell : bash
276+ env :
277+ EXAMPLE : ${{ matrix.example }}
273278 run : |
274279 echo "forks=20" > scoredirector-benchmark.properties
275280 echo "warmup_iterations=5" >> scoredirector-benchmark.properties
276281 echo "measurement_iterations=5" >> scoredirector-benchmark.properties
277282 echo "relative_score_error_threshold=0.02" >> scoredirector-benchmark.properties
278283 echo "score_director_type=cs" >> scoredirector-benchmark.properties
279- echo "example=${{ matrix.example }} " >> scoredirector-benchmark.properties
284+ echo "example=$EXAMPLE " >> scoredirector-benchmark.properties
280285 cat scoredirector-benchmark.properties
281286 chmod +x run-scoredirector.sh
282287
@@ -309,9 +314,9 @@ jobs:
309314 mkdir target
310315 cp benchmarks-baseline.jar target/benchmarks.jar
311316 ./run-scoredirector.sh
312- echo "RANGE_START=$(jq '.[0].primaryMetric.scoreConfidence[0]|round' results/scoredirector/${{ env. RUN_ID }} /results.json)" >> "$GITHUB_OUTPUT"
313- echo "RANGE_END=$(jq '.[0].primaryMetric.scoreConfidence[1]|round' results/scoredirector/${{ env. RUN_ID }} /results.json)" >> "$GITHUB_OUTPUT"
314- echo "RANGE_MID=$(jq '.[0].primaryMetric.score|round' results/scoredirector/${{ env. RUN_ID }} /results.json)" >> "$GITHUB_OUTPUT"
317+ echo "RANGE_START=$(jq '.[0].primaryMetric.scoreConfidence[0]|round' results/scoredirector/$RUN_ID/results.json)" >> "$GITHUB_OUTPUT"
318+ echo "RANGE_END=$(jq '.[0].primaryMetric.scoreConfidence[1]|round' results/scoredirector/$RUN_ID/results.json)" >> "$GITHUB_OUTPUT"
319+ echo "RANGE_MID=$(jq '.[0].primaryMetric.score|round' results/scoredirector/$RUN_ID/results.json)" >> "$GITHUB_OUTPUT"
315320
316321 - name : (SUT) Setup JDK and Maven
317322 uses : actions/setup-java@v5
@@ -331,28 +336,32 @@ jobs:
331336 rm target/benchmarks.jar
332337 cp benchmarks-sut.jar target/benchmarks.jar
333338 ./run-scoredirector.sh
334- echo "RANGE_START=$(jq '.[0].primaryMetric.scoreConfidence[0]|round' results/scoredirector/${{ env. RUN_ID }} /results.json)" >> "$GITHUB_OUTPUT"
335- echo "RANGE_END=$(jq '.[0].primaryMetric.scoreConfidence[1]|round' results/scoredirector/${{ env. RUN_ID }} /results.json)" >> "$GITHUB_OUTPUT"
336- echo "RANGE_MID=$(jq '.[0].primaryMetric.score|round' results/scoredirector/${{ env. RUN_ID }} /results.json)" >> "$GITHUB_OUTPUT"
339+ echo "RANGE_START=$(jq '.[0].primaryMetric.scoreConfidence[0]|round' results/scoredirector/$RUN_ID/results.json)" >> "$GITHUB_OUTPUT"
340+ echo "RANGE_END=$(jq '.[0].primaryMetric.scoreConfidence[1]|round' results/scoredirector/$RUN_ID/results.json)" >> "$GITHUB_OUTPUT"
341+ echo "RANGE_MID=$(jq '.[0].primaryMetric.score|round' results/scoredirector/$RUN_ID/results.json)" >> "$GITHUB_OUTPUT"
337342
338343 - name : Clean up the data
339344 working-directory : ./timefold-solver-benchmarks
340345 shell : bash
346+ env :
347+ BASELINE_DIR : ${{ env.BASELINE_DIR }}
348+ SUT_DIR : ${{ env.SUT_DIR }}
349+ EXAMPLE : ${{ matrix.example }}
341350 run : |
342- cd results/scoredirector/${{ env. BASELINE_DIR }}
343- mv $(find . -maxdepth 1 -mindepth 1 -type d -print -quit) ../../../${{ env. BASELINE_DIR }}
351+ cd results/scoredirector/$BASELINE_DIR
352+ mv $(find . -maxdepth 1 -mindepth 1 -type d -print -quit) ../../../$BASELINE_DIR
344353 cd ../../../
345- mv ${{ env. BASELINE_DIR }} /jfr-cpu.jfr ${{ env. BASELINE_DIR }}/${{ matrix.example }}-${{ env. BASELINE_DIR }} .jfr
354+ mv $BASELINE_DIR/jfr-cpu.jfr $BASELINE_DIR/$EXAMPLE-$ BASELINE_DIR.jfr
346355
347- cd results/scoredirector/${{ env. SUT_DIR }}
348- mv $(find . -maxdepth 1 -mindepth 1 -type d -print -quit) ../../../${{ env. SUT_DIR }}
356+ cd results/scoredirector/$SUT_DIR
357+ mv $(find . -maxdepth 1 -mindepth 1 -type d -print -quit) ../../../$SUT_DIR
349358 cd ../../../
350- mv ${{ env. SUT_DIR }} /jfr-cpu.jfr ${{ env. SUT_DIR }}/${{ matrix.example }}-${{ env. SUT_DIR }} .jfr
359+ mv $SUT_DIR/jfr-cpu.jfr $SUT_DIR/$EXAMPLE-$ SUT_DIR.jfr
351360
352361 - name : Archive benchmark data
353362 uses : actions/upload-artifact@v7
354363 with :
355- name : assets-${{ matrix.example }}-${{ env.SANITIZED_BASELINE }}_vs_ ${{ env.SANITIZED_BRANCH }}
364+ name : assets-${{ matrix.example }}-${{ env.SANITIZED_BASELINE }}-vs- ${{ env.SANITIZED_BRANCH }}
356365 path : |
357366 ./timefold-solver-benchmarks/scoredirector-benchmark.properties
358367 ./timefold-solver-benchmarks/${{ env.BASELINE_DIR }}/*.jfr
@@ -365,6 +374,9 @@ jobs:
365374 - name : Report results
366375 working-directory : ./timefold-solver-benchmarks
367376 env :
377+ BASELINE : ${{ github.event.inputs.baseline }}
378+ BRANCH : ${{ github.event.inputs.branch }}
379+ OWNER : ${{ github.event.inputs.branch_owner }}
368380 BASELINE_RANGE_START : ${{ steps.benchmark_baseline.outputs.RANGE_START }}
369381 BASELINE_RANGE_MID : ${{ steps.benchmark_baseline.outputs.RANGE_MID }}
370382 BASELINE_RANGE_END : ${{ steps.benchmark_baseline.outputs.RANGE_END }}
@@ -391,17 +403,17 @@ jobs:
391403 FAIL=true
392404 fi
393405
394- if [[ "${{ github.event.inputs.baseline }} " =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
395- BASELINE_URL="https://github.com/TimefoldAI/timefold-solver/releases/tag/${{ github.event.inputs.baseline }} "
406+ if [[ "$BASELINE " =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
407+ BASELINE_URL="https://github.com/TimefoldAI/timefold-solver/releases/tag/$BASELINE "
396408 else
397- BASELINE_URL="https://github.com/TimefoldAI/timefold-solver/tree/${{ github.event.inputs.baseline }} "
409+ BASELINE_URL="https://github.com/TimefoldAI/timefold-solver/tree/$BASELINE "
398410 fi
399- SUT_URL="https://github.com/${{ github.event.inputs.branch_owner }} /timefold-solver/tree/${{ github.event.inputs.branch }} "
411+ SUT_URL="https://github.com/$OWNER /timefold-solver/tree/$BRANCH "
400412
401413 echo "| | **Ref** | **Mean** |" >> $GITHUB_STEP_SUMMARY
402414 echo "|:------:|:-----------:|:-----------------:|" >> $GITHUB_STEP_SUMMARY
403- echo "| _Old_ | [TimefoldAI's ${{ github.event.inputs.baseline }} ]($BASELINE_URL) | $BASELINE_RANGE_MID ± $BASELINE_DEV % |" >> $GITHUB_STEP_SUMMARY
404- echo "| _New_ | [${{ github.event.inputs.branch_owner }} 's ${{ github.event.inputs.branch }} ]($SUT_URL) | $SUT_RANGE_MID ± $SUT_DEV % |" >> $GITHUB_STEP_SUMMARY
415+ echo "| _Old_ | [TimefoldAI's $BASELINE ]($BASELINE_URL) | $BASELINE_RANGE_MID ± $BASELINE_DEV % |" >> $GITHUB_STEP_SUMMARY
416+ echo "| _New_ | [$OWNER 's $BRANCH ]($SUT_URL) | $SUT_RANGE_MID ± $SUT_DEV % |" >> $GITHUB_STEP_SUMMARY
405417 echo "| _Diff_ | | $DIFF_MID % |" >> $GITHUB_STEP_SUMMARY
406418
407419 echo "" >> $GITHUB_STEP_SUMMARY
0 commit comments