Skip to content
Open
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
137 changes: 137 additions & 0 deletions .github/workflows/zip-sbom.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: Generate ZIP + SBOM

on:
release:
types: [published]

jobs:
build_artifact:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.0'
extensions: dom, curl, json
tools: wp-cli

- name: Check for composer.json
id: composer-check
run: |
if [ -f "composer.json" ]; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi
- name: Get Composer Cache Directory
if: steps.composer-check.outputs.exists == 'true'
id: composer-cache-dir
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT

- name: Cache Composer dependencies
if: steps.composer-check.outputs.exists == 'true'
uses: actions/cache@v4
with:
path: ${{ steps.composer-cache-dir.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install PHP dependencies
if: steps.composer-check.outputs.exists == 'true'
run: composer install --no-dev --optimize-autoloader --no-interaction

# Check for npm
- name: Check for package.json
id: npm-check
run: |
if [ -f "package.json" ]; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Setup Node.js
if: steps.npm-check.outputs.exists == 'true'
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'

- name: Install Node.js dependencies
if: steps.npm-check.outputs.exists == 'true'
run: npm ci

- name: Check for build script
if: steps.npm-check.outputs.exists == 'true'
id: build-check
run: |
if node -e "const pkg = require('./package.json'); process.exit(pkg.scripts && pkg.scripts.build ? 0 : 1);" 2>/dev/null; then
echo "exists=true" >> $GITHUB_OUTPUT
else
echo "exists=false" >> $GITHUB_OUTPUT
fi

- name: Build production assets
if: steps.npm-check.outputs.exists == 'true' && steps.build-check.outputs.exists == 'true'
run: npm run build

# === Generate SBOM before creating the build ===
- name: Install Syft
run: |
curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin

- name: Generate SBOM
run: syft . -o cyclonedx-json=sbom-${{ github.event.release.tag_name }}.json

# === Build plugin ===
- name: Install latest version of dist-archive-command
run: wp package install wp-cli/dist-archive-command:@stable

- name: Build plugin
run: |
wp dist-archive . ./${{ github.event.repository.name }}.zip

# === Check that the SBOM was generated ===
- name: Verify SBOM exists
run: |
if [ ! -f "sbom-${{ github.event.release.tag_name }}.json" ]; then
echo "SBOM generation failed"
exit 1
fi

# === Get existing release body and append SBOM info ===
- name: Get existing release body
id: release-body
run: |
EXISTING_BODY=$(curl -s \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
"https://api.github.com/repos/${{ github.repository }}/releases/tags/${{ github.event.release.tag_name }}" \
| jq -r '.body // ""')

# Append SBOM information to existing body
SBOM_INFO=$'SBOM Format: CycloneDX JSON\nGenerated with: Syft'

if [ -z "$EXISTING_BODY" ]; then
COMBINED_BODY="$SBOM_INFO"
else
COMBINED_BODY="$EXISTING_BODY"$'\n\n'"$SBOM_INFO"
fi

# Write to file for body_path
echo "$COMBINED_BODY" > release-body.txt
echo "body_path=release-body.txt" >> $GITHUB_OUTPUT

# === Upload both artifact and SBOM to release ===
- name: Upload artifact to release
uses: softprops/action-gh-release@v1
with:
files: |
sbom-${{ github.event.release.tag_name }}.json
${{ github.event.repository.name }}.zip
body_path: ${{ steps.release-body.outputs.body_path }}