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
47 changes: 47 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
name: CodeQL

on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 6 * * 1'

permissions:
contents: read

jobs:
analyze:
name: Analyze (Java)
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
security-events: write
packages: read
actions: read
contents: read

steps:
- uses: actions/checkout@v6

- uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
cache: 'maven'

- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: java-kotlin
queries: security-and-quality

- name: Build with Maven
run: ./mvnw -B -ntp clean compile -DskipTests

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:java-kotlin"
80 changes: 76 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
name: Release

permissions:
contents: write
packages: write
statuses: write
checks: write
contents: read

on:
workflow_dispatch:
Expand All @@ -14,7 +11,11 @@ jobs:
release:
permissions:
contents: write
packages: write
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.publish.outputs.tag }}
version: ${{ steps.publish.outputs.version }}
steps:
- uses: actions/checkout@v6
- uses: webfactory/ssh-agent@v0.10.0
Expand All @@ -32,13 +33,16 @@ jobs:
gpg-passphrase: MAVEN_GPG_PASSPHRASE

- name: Publish package to Maven Central
id: publish
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
mvn -B -ntp -Dstyle.color=always release:prepare
cat release.properties
TAG=$(grep 'scm.tag=' release.properties | cut -d'=' -f2)
VERSION=${TAG#v}
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
mvn -B -ntp -Dstyle.color=always release:perform -DconnectionUrl=scm:git:https://github.com/${{ github.repository }}.git
echo "Released ${TAG} 🚀" >> $GITHUB_STEP_SUMMARY
env:
Expand All @@ -65,3 +69,71 @@ jobs:
git push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Attestations and the GitHub Release SBOM upload run in a separate job so
# the OIDC token (id-token: write) and attestations: write permission are
# never available to the preceding `mvn release:*` steps, which execute
# repository-controlled plugin code. If this job fails after Maven Central
# has accepted the version, the release job stays green (the publish did
# succeed), this job is visibly red, and "Re-run failed jobs" reruns only
# the attestation/Release steps without retrying the Central publish.
# The job checks out the release tag so that provenance is anchored to the
# tagged release commit (not the pre-release snapshot commit that triggered
# the workflow_dispatch), and rebuilds the artifacts cleanly from that commit.
attest:
needs: release
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
attestations: write
steps:
- name: Checkout release tag
uses: actions/checkout@v6
with:
ref: ${{ needs.release.outputs.tag }}

- name: Set up Java
uses: actions/setup-java@v5
with:
java-version: "17"
distribution: "temurin"
cache: "maven"

- name: Build release artifacts at tagged commit
run: mvn -B -ntp package -DskipTests -Dgpg.skip=true

- name: Attest build provenance for release artifacts
uses: actions/attest-build-provenance@v2
with:
subject-path: |
target/elearning-module-parser-*.jar
!target/elearning-module-parser-*-sources.jar
!target/elearning-module-parser-*-javadoc.jar

- name: Attest SBOM for release artifacts
uses: actions/attest-sbom@v2
with:
subject-path: |
target/elearning-module-parser-*.jar
!target/elearning-module-parser-*-sources.jar
!target/elearning-module-parser-*-javadoc.jar
sbom-path: target/elearning-module-parser-*-cyclonedx.json

- name: Upload SBOM to GitHub Release
run: |
TAG="${{ needs.release.outputs.tag }}"
if gh release view "${TAG}" >/dev/null 2>&1; then
gh release upload "${TAG}" \
target/elearning-module-parser-*-cyclonedx.json \
target/elearning-module-parser-*-cyclonedx.xml \
--clobber
else
gh release create "${TAG}" \
target/elearning-module-parser-*-cyclonedx.json \
target/elearning-module-parser-*-cyclonedx.xml \
--title "${TAG}" \
--generate-notes
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59 changes: 59 additions & 0 deletions .github/workflows/snapshot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,62 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}

# Stage post-deploy artifacts (these are exactly what GitHub Packages
# received, since `mvn deploy` re-runs the package phase and overwrites
# target/) for the separate attest job to consume.
- name: Stage snapshot artifacts for attestation
if: github.event_name != 'pull_request'
run: |
mkdir -p snapshot-artifacts
cp target/elearning-module-parser-*.jar snapshot-artifacts/
cp target/elearning-module-parser-*-cyclonedx.json snapshot-artifacts/
cp target/elearning-module-parser-*-cyclonedx.xml snapshot-artifacts/

- name: Upload snapshot artifacts for attestation job
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@v4
with:
name: snapshot-artifacts
path: snapshot-artifacts/
if-no-files-found: error

# Attestations run in a separate job so id-token: write and
# attestations: write are not available to the preceding Maven build,
# which executes repository-controlled plugin code.
attest:
needs: test-build
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
permissions:
id-token: write
attestations: write
steps:
- name: Download snapshot artifacts
uses: actions/download-artifact@v4
with:
name: snapshot-artifacts
path: artifacts

- name: Attest build provenance for snapshot artifacts
uses: actions/attest-build-provenance@v2
with:
subject-path: artifacts/elearning-module-parser-*.jar

- name: Attest SBOM for snapshot artifacts
uses: actions/attest-sbom@v2
with:
subject-path: |
artifacts/elearning-module-parser-*.jar
!artifacts/elearning-module-parser-*-sources.jar
!artifacts/elearning-module-parser-*-javadoc.jar
sbom-path: artifacts/elearning-module-parser-*-cyclonedx.json

- name: Upload SBOM as workflow artifact
uses: actions/upload-artifact@v4
with:
name: sbom
path: |
artifacts/elearning-module-parser-*-cyclonedx.json
artifacts/elearning-module-parser-*-cyclonedx.xml
if-no-files-found: error
23 changes: 23 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
<version.org.json>20251224</version.org.json>
<version.plugin.central-publishing>0.10.0</version.plugin.central-publishing>
<version.plugin.compiler>3.15.0</version.plugin.compiler>
<version.plugin.cyclonedx>2.9.1</version.plugin.cyclonedx>
<version.plugin.exec>3.6.3</version.plugin.exec>
<version.plugin.failsafe>3.5.5</version.plugin.failsafe>
<version.plugin.gpg>3.2.8</version.plugin.gpg>
Expand Down Expand Up @@ -401,6 +402,28 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.cyclonedx</groupId>
<artifactId>cyclonedx-maven-plugin</artifactId>
<version>${version.plugin.cyclonedx}</version>
<executions>
<execution>
<id>make-bom</id>
<phase>package</phase>
<goals>
<goal>makeAggregateBom</goal>
</goals>
</execution>
</executions>
<configuration>
<projectType>library</projectType>
<schemaVersion>1.6</schemaVersion>
<outputFormat>all</outputFormat>
<outputName>${project.artifactId}-${project.version}-cyclonedx</outputName>
<includeBomSerialNumber>true</includeBomSerialNumber>
<includeTestScope>false</includeTestScope>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
Expand Down
Loading