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
5 changes: 5 additions & 0 deletions .github/workflows/apple-container.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ on:
- ".github/workflows/apple-container.yml"
permissions:
contents: read
# Cancel superseded runs on the same branch so rapid pushes don't keep premium macOS runners alive.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
cli-surface:
name: Verify Apple container CLI surface
# The .pkg targets macOS 26 (Tahoe); the chip is still M1, which is fine for help-only checks.
runs-on: macos-26
timeout-minutes: 20
steps:
- id: install
name: Install Apple container
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/cache-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@ on:
- 'skills/ilo/**'
- '.github/scripts/**'
- '.github/workflows/cache-examples.yml'
# Cancel superseded runs on the same branch so rapid docs/skill pushes don't stack native builds.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Runs untrusted PR code; the token needs only read access to the checkout.
permissions:
contents: read
jobs:
cache-examples:
name: Verify documented examples
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- id: checkout
name: Clone Git Repository
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/cache-warm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ jobs:
warm-maven:
name: Warm Maven cache
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- id: checkout
name: Clone Git Repository
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/dependabot-automerge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ permissions:
jobs:
dependabot:
runs-on: ubuntu-latest
timeout-minutes: 5
if: ${{ github.event.pull_request.user.login == 'dependabot[bot]' }}
steps:
- name: Dependabot metadata
Expand Down
59 changes: 41 additions & 18 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@ on:
schedule:
- cron: 45 3 * * MON
workflow_dispatch:
# Default to read-only; only the release job below is granted contents: write to publish the release.
permissions:
contents: read
jobs:
prepare:
name: Prepare Release
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
commit_count: ${{ steps.commits.outputs.count }}
release_version: ${{ steps.release.outputs.version }}
Expand All @@ -24,23 +28,43 @@ jobs:
fetch-depth: 0
- id: last_release
name: Fetch last release info
run: echo "tag=$(gh release view --json tagName --jq '.tagName')" >> $GITHUB_OUTPUT
# Capture into a variable on its own line so a failing 'gh' aborts the step instead of writing
# an empty tag (which would silently corrupt the commit count and version gating below).
run: |
set -euo pipefail
tag=$(gh release view --json tagName --jq '.tagName')
echo "tag=$tag" >> "$GITHUB_OUTPUT"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- id: commits
name: Count Commits
run: echo "count=$(git rev-list --count ${{ steps.last_release.outputs.tag }}..HEAD -- src/main/java pom.xml)" >> $GITHUB_OUTPUT
env:
PREVIOUS_TAG: ${{ steps.last_release.outputs.tag }}
run: |
set -euo pipefail
count=$(git rev-list --count "${PREVIOUS_TAG}..HEAD" -- src/main/java pom.xml)
echo "count=$count" >> "$GITHUB_OUTPUT"
- id: release
name: Create Release Version
if: steps.commits.outputs.count > 0
run: echo "version=$(date +'%Y.%-m.%-d')" >> $GITHUB_OUTPUT
run: |
set -euo pipefail
version=$(date +'%Y.%-m.%-d')
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Build Timestamp
id: timestamp
run: echo "iso8601=$(date --utc --iso-8601=seconds)" >> $GITHUB_OUTPUT
run: |
set -euo pipefail
iso8601=$(date --utc --iso-8601=seconds)
echo "iso8601=$iso8601" >> "$GITHUB_OUTPUT"
build:
name: Build on ${{ matrix.os }}
needs: prepare
# Gate the whole job so no runner is provisioned on weeks without qualifying commits, and a future
# step added without its own guard cannot run unconditionally.
if: needs.prepare.outputs.commit_count > 0
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
matrix:
os:
Expand All @@ -50,19 +74,16 @@ jobs:
steps:
- id: checkout
name: Clone Git Repository
if: needs.prepare.outputs.commit_count > 0
uses: actions/checkout@v6
- id: graal
name: GraalVM Setup
if: needs.prepare.outputs.commit_count > 0
uses: graalvm/setup-graalvm@v1
with:
distribution: graalvm-community
java-version: 25
github-token: ${{ secrets.GITHUB_TOKEN }}
- id: cache
name: Cache Maven Repository
if: needs.prepare.outputs.commit_count > 0
uses: actions/cache@v5
with:
path: ~/.m2/repository
Expand All @@ -72,28 +93,28 @@ jobs:
maven-
- id: gpg
name: GPG Key
if: needs.prepare.outputs.commit_count > 0
uses: timheuer/base64-to-file@v2.0
with:
fileName: signing.key.asc
fileDir: ${{ github.workspace}}
encodedString: ${{ secrets.GPG_SECRET_KEY_BASE64 }}
- id: verify
if: needs.prepare.outputs.commit_count > 0
name: Verify Project
# The signing passphrase goes through SIGN_KEY_PASS (which the sign plugin reads with priority)
# rather than a -D property, so it is not exposed in the runner's process table.
env:
SIGN_KEY_PASS: ${{ secrets.GPG_SECRET_KEY_PASSWORD }}
run: >
mvn
--batch-mode
--activate-profiles release
--define revision=${{ needs.prepare.outputs.release_version }}
--define skipNativeBuild=false
--define sign.keyFile=signing.key.asc
--define sign.keyPass=${{ secrets.GPG_SECRET_KEY_PASSWORD }}
--define project.build.outputTimestamp=${{ needs.prepare.outputs.build_timestamp }}
verify
- id: smoke
name: Smoke test the native binary
if: needs.prepare.outputs.commit_count > 0
shell: bash
# Run the freshly built binary so a native-only failure (a missing reflection/resource
# registration) fails the release here instead of shipping a binary that crashes on first run.
Expand All @@ -103,54 +124,53 @@ jobs:
"$bin" --help
- id: upload-java
name: Upload JVM Artifact
if: needs.prepare.outputs.commit_count > 0 && runner.os == 'Linux'
if: runner.os == 'Linux'
uses: actions/upload-artifact@v6
with:
name: jvm
path: ./target/ilo-*-jvm*
- id: upload-linux
name: Upload Linux Artifact
if: needs.prepare.outputs.commit_count > 0 && runner.os == 'Linux'
if: runner.os == 'Linux'
uses: actions/upload-artifact@v6
with:
name: linux
path: ./target/ilo-*-linux*
- id: upload-mac
name: Upload Mac Artifact
if: needs.prepare.outputs.commit_count > 0 && runner.os == 'macOS'
if: runner.os == 'macOS'
uses: actions/upload-artifact@v6
with:
name: mac
path: ./target/ilo-*-mac*
- id: upload-windows
name: Upload Windows Artifact
if: needs.prepare.outputs.commit_count > 0 && runner.os == 'Windows'
if: runner.os == 'Windows'
uses: actions/upload-artifact@v6
with:
name: windows
path: ./target/ilo-*-windows*
release:
name: GitHub Release
needs: [prepare, build]
if: needs.prepare.outputs.commit_count > 0
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
steps:
- id: checkout
name: Clone Git Repository
if: needs.prepare.outputs.commit_count > 0
uses: actions/checkout@v6
with:
fetch-depth: 0
- id: download
name: Download Artifacts
if: needs.prepare.outputs.commit_count > 0
uses: actions/download-artifact@v8
with:
path: artifacts
- id: create_release
name: Create Release
if: needs.prepare.outputs.commit_count > 0
uses: softprops/action-gh-release@v3
with:
tag_name: ${{ needs.prepare.outputs.release_version }}
Expand All @@ -159,6 +179,9 @@ jobs:
draft: false
prerelease: false
generate_release_notes: true
# Fail the release if any expected asset is missing rather than publishing an incomplete set;
# the upload steps use globs, so a filename diverging from release_version would otherwise pass.
fail_on_unmatched_files: true
files: |
artifacts/jvm/ilo-${{ needs.prepare.outputs.release_version }}-jvm.tar.gz
artifacts/jvm/ilo-${{ needs.prepare.outputs.release_version }}-jvm.tar.gz.asc
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/reuse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ on:
branches: [ main ]
pull_request:
branches: [ main ]
permissions:
contents: read
jobs:
reuse:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout
uses: actions/checkout@v6
Expand Down
12 changes: 10 additions & 2 deletions .github/workflows/sonar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@
# SPDX-License-Identifier: 0BSD

name: SonarQube Cloud
# Main-branch analysis only: it establishes the new-code baseline. Pull-request analysis runs inside
# verify.yml, reusing that job's test run so the PR scan is not a second full build.
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Cancel superseded analyses on the same branch; a newer push makes an in-flight Sonar run obsolete.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Analysis only reads the checkout; Sonar auth is via SONAR_TOKEN, not the GITHUB_TOKEN.
permissions:
contents: read
jobs:
sonar:
name: Analyze
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- id: checkout
name: Clone Git Repository
Expand Down
23 changes: 23 additions & 0 deletions .github/workflows/verify.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ name: Verify Commits
on:
pull_request:
branches: [ main ]
# Cancel superseded runs on the same branch so rapid pushes don't keep stale 3-OS native builds alive.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# These jobs run untrusted PR code; the token needs only read access to the checkout.
permissions:
contents: read
jobs:
verify:
name: Build on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
matrix:
os:
Expand All @@ -18,7 +26,10 @@ jobs:
steps:
- id: checkout
name: Clone Git Repository
# Full history so the Linux leg's SonarQube analysis can assign blame and compute the new-code period.
uses: actions/checkout@v6
with:
fetch-depth: 0
- id: graal
name: Set up GraalVM
uses: graalvm/setup-graalvm@v1
Expand Down Expand Up @@ -47,9 +58,20 @@ jobs:
bin="target/ilo"; [ -f "target/ilo.exe" ] && bin="target/ilo.exe"
"$bin" --version
"$bin" --help
- id: sonar
name: SonarQube analysis
# Linux-only, and skipped on fork PRs (which cannot read SONAR_TOKEN). Reuses the test run and
# coverage data the verify step already produced, so the PR scan adds no second build. The
# push-to-main analysis (the new-code baseline this decoration compares against) lives in sonar.yml.
if: runner.os == 'Linux' && github.event.pull_request.head.repo.fork == false
run: mvn --batch-mode org.jacoco:jacoco-maven-plugin:report sonar:sonar
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
mutation:
name: Mutation tests (PIT)
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- id: checkout
name: Clone Git Repository
Expand Down Expand Up @@ -78,6 +100,7 @@ jobs:
integration:
name: Integration tests (Docker)
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- id: checkout
name: Clone Git Repository
Expand Down
19 changes: 11 additions & 8 deletions .github/workflows/website.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,34 @@ on:
- main
paths:
- docs/**
# Read-only by default so a compromised build/link-check step can't reach a write-scoped token; the
# deploy job is granted exactly the contents: write that pushing to the gh-pages branch requires.
permissions:
contents: read
jobs:
website:
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
steps:
- id: checkout
name: Clone Git Repository
# Shallow clone: the Hugo site does not use Git info, so full history is unnecessary.
uses: actions/checkout@v6
with:
fetch-depth: 0
- id: hugo
name: Setup Hugo
uses: peaceiris/actions-hugo@v3
with:
hugo-version: 0.162.1
- id: previous
name: Get Last Release
run: echo "version=$(git describe --abbrev=0 --tags)" >> "$GITHUB_OUTPUT"
- id: build
name: Build Website
run: hugo --minify --printI18nWarnings --printPathWarnings --printUnusedTemplates --source docs
env:
ILO_RELEASE: ${{ steps.previous.outputs.version }}
- id: htmltest
name: Run htmltest
uses: wjdp/htmltest-action@master
# Pinned to an immutable commit SHA: the action's only tag is an old RC, so it is otherwise
# consumed from the mutable 'master' branch. This is master HEAD (2023-03-28); Dependabot bumps it.
uses: wjdp/htmltest-action@31be84a95c860a331e0cf9a99f71e3eb39d2f86b
with:
config: ./docs/htmltest.yml
- id: deploy
Expand Down
Loading