Release pipeline #161
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Release pipeline | |
on: | |
push: | |
# only for version 2.x.x releases and release candidates | |
tags: | |
- v2.?.? | |
- v2.?.?-RC? | |
workflow_dispatch: | |
env: | |
# threatdragon is the working area on docker hub so use this area | |
# owasp/threat-dragon is the final release area so DO NOT use that | |
IMAGE_NAME: threatdragon/owasp-threat-dragon | |
# for security reasons the github actions are pinned to specific release versions | |
jobs: | |
site_unit_tests: | |
name: Site unit tests | |
runs-on: ubuntu-24.04 | |
defaults: | |
run: | |
working-directory: td.vue | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install packages | |
run: npm clean-install | |
- name: lint | |
run: npm run lint | |
- name: Unit test | |
run: npm run test:unit | |
server_unit_tests: | |
name: Server unit tests | |
runs-on: ubuntu-24.04 | |
defaults: | |
run: | |
working-directory: td.server | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install packages | |
run: npm clean-install | |
- name: lint | |
run: npm run lint | |
- name: Unit test | |
run: npm run test:unit | |
- name: Create server SBOM | |
run: npm run make-sbom | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms-server | |
path: './td.server/sbom.*' | |
include-hidden-files: true | |
desktop_unit_tests: | |
name: Desktop unit tests | |
runs-on: ubuntu-24.04 | |
defaults: | |
run: | |
working-directory: td.vue | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install packages | |
run: npm clean-install | |
- name: lint | |
run: npm run lint:desktop | |
- name: Unit test | |
run: npm run test:desktop | |
desktop_windows: | |
# Build only Windows installer and provide to github Release Draft | |
name: Windows installer | |
runs-on: windows-latest | |
needs: [desktop_unit_tests, site_unit_tests] | |
defaults: | |
run: | |
working-directory: td.vue | |
steps: | |
- name: Check out | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install clean packages | |
run: npm clean-install | |
- name: Build Windows executable | |
# code signing done later using Extended Verification (EV) with a hardware key | |
run: npm run build:desktop -- --windows --publish never | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms-desktop-windows-site | |
path: './td.vue/dist-desktop/bundled/.sbom/*' | |
include-hidden-files: true | |
if-no-files-found: error | |
desktop_macos: | |
# Build and publish MacOS installer to github Release Draft | |
# the draft name uses version and is created if it does not already exist | |
name: MacOS installer | |
runs-on: macos-latest | |
needs: [desktop_unit_tests, site_unit_tests] | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
# MacOS signing: certificate and password, see electron.build/code-signing | |
CSC_KEY_PASSWORD: ${{ secrets.MAC_CERTS_PASSWORD }} | |
CSC_LINK: ${{ secrets.MAC_CERTS }} | |
# MacOS notarization: see github.com/electron/notarize#readme | |
API_KEY_ID: ${{ secrets.API_KEY_ID }} | |
API_KEY_ISSUER_ID: ${{ secrets.API_KEY_ISSUER_ID }} | |
# APPLE_ID: ${{ secrets.APPLE_ID }} | |
# APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} | |
# APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
defaults: | |
run: | |
working-directory: td.vue | |
steps: | |
- name: Check out | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install clean packages | |
run: npm clean-install | |
- name: Prepare for MacOS notarization | |
# Import Apple API key to support signing of app | |
run: | | |
mkdir -p ~/private_keys/ | |
echo '${{ secrets.API_KEY }}' > ~/private_keys/AuthKey_${{ secrets.API_KEY_ID }}.p8 | |
- name: Publish MacOS disk image | |
run: npm run build:desktop -- --mac --publish always | |
- name: Print logs on error | |
if: ${{ failure() }} | |
run: find . -name "*.log" -exec cat '{}' \; -print | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms-desktop-macos-site | |
path: './td.vue/dist-desktop/bundled/.sbom/*' | |
include-hidden-files: true | |
if-no-files-found: error | |
desktop_linux: | |
name: Linux installers | |
runs-on: ubuntu-24.04 | |
needs: [desktop_unit_tests, site_unit_tests] | |
defaults: | |
run: | |
working-directory: td.vue | |
steps: | |
- name: Check out | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install clean packages | |
run: npm clean-install | |
# Build and publish Linux installers to github Release Draft | |
# for all linux images EXCEPT for the snap | |
# Snaps do not publish, even with snapcraft installed, so use Snap Store | |
- name: Publish Linux app images | |
shell: bash | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
run: npm run build:desktop -- --linux AppImage deb rpm --publish always | |
- name: Print logs on error | |
if: ${{ failure() }} | |
run: find . -name "*.log" -exec cat '{}' \; -print | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms-desktop-linux-site | |
path: './td.vue/dist-desktop/bundled/.sbom/*' | |
include-hidden-files: true | |
if-no-files-found: error | |
desktop_linux_snap: | |
name: Linux snap | |
runs-on: ubuntu-24.04 | |
needs: [desktop_unit_tests, site_unit_tests] | |
env: | |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_TOKEN }} | |
defaults: | |
run: | |
working-directory: td.vue | |
steps: | |
- name: Check out | |
uses: actions/checkout@v4.2.0 | |
- name: Use node LTS 20.14.0 | |
uses: actions/setup-node@v4.1.0 | |
with: | |
node-version: '20.14.0' | |
- name: Cache NPM dir | |
uses: actions/cache@v4.1.1 | |
with: | |
path: ~/.npm | |
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} | |
restore-keys: | | |
${{ runner.os }}-node- | |
${{ runner.os }}- | |
- name: Install clean packages | |
run: | | |
sudo snap install snapcraft --classic | |
npm clean-install | |
# Build the snap, but do not use inbuilt publish | |
# Snaps do not publish, even with snapcraft installed, so use Snap Store | |
- name: Build Linux snap | |
shell: bash | |
run: npm run build:desktop -- --linux snap | |
- name: Upload to Snap Store | |
shell: bash | |
run: snapcraft upload --release=stable dist-desktop/threat-dragon*.snap | |
- name: Print logs on error | |
if: ${{ failure() }} | |
run: find . -name "*.log" -exec cat '{}' \; -print | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms-desktop-linux-snap-site | |
path: './td.vue/dist-desktop/bundled/.sbom/*' | |
include-hidden-files: true | |
if-no-files-found: error | |
dockerhub_release: | |
name: Publish to dockerhub | |
runs-on: ubuntu-24.04 | |
needs: [server_unit_tests, site_unit_tests] | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v4.2.0 | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3.2.0 | |
- name: Set up Docker Buildx | |
id: buildx | |
uses: docker/setup-buildx-action@v3.7.0 | |
with: | |
install: true | |
- name: Cache Docker layers | |
uses: actions/cache@v4.1.1 | |
with: | |
path: /tmp/.buildx-cache | |
key: ${{ runner.os }}-buildx-${{ hashFiles('Dockerfile') }} | |
restore-keys: | | |
${{ runner.os }}-buildx- | |
${{ runner.os }}- | |
- name: Login to Docker Hub | |
uses: docker/login-action@v3.3.0 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_TOKEN }} | |
# platform manifests not (yet) supported, so split out architectures | |
- name: Build for amd64 and push to Docker Hub | |
id: docker_build_amd64 | |
uses: docker/build-push-action@v6.10.0 | |
with: | |
context: ./ | |
file: ./Dockerfile | |
builder: ${{ steps.buildx.outputs.name }} | |
push: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
tags: ${{ env.IMAGE_NAME }}:${{ github.ref_name }},${{ env.IMAGE_NAME }}:stable | |
cache-from: type=local,src=/tmp/.buildx-cache | |
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max | |
platforms: linux/amd64 | |
load: true | |
- name: Build for arm64 and push to Docker Hub | |
id: docker_build_arm64 | |
uses: docker/build-push-action@v6.10.0 | |
with: | |
context: ./ | |
file: ./Dockerfile | |
builder: ${{ steps.buildx.outputs.name }} | |
push: ${{ startsWith(github.ref, 'refs/tags/v') }} | |
tags: ${{ env.IMAGE_NAME }}:${{ github.ref_name }}-arm64 | |
cache-from: type=local,src=/tmp/.buildx-cache | |
cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max | |
platforms: linux/arm64 | |
load: true | |
- name: fetch app SBOM | |
run: docker run --rm --entrypoint tar "$IMAGE_ID" -c boms | tar -xv | |
env: | |
IMAGE_ID: ${{ steps.docker_build_amd64.outputs.imageid }} | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms-container-image-app | |
path: './boms/*' | |
include-hidden-files: true | |
if-no-files-found: error | |
- # Temp fix for large cache bug | |
# https://github.com/docker/build-push-action/issues/252 | |
name: Move cache | |
run: | | |
rm -rf /tmp/.buildx-cache | |
mv /tmp/.buildx-cache-new /tmp/.buildx-cache | |
sbom_combiner: | |
name: SBOM combiner | |
runs-on: ubuntu-24.04 | |
needs: | |
- server_unit_tests | |
- desktop_macos | |
- desktop_linux | |
- desktop_linux_snap | |
- desktop_windows | |
- dockerhub_release | |
steps: | |
- name: Fetch prepared SBOM artifacts | |
uses: actions/download-artifact@v4.1.7 | |
with: | |
pattern: 'sboms-*' | |
merge-multiple: false | |
path: 'raw/' | |
- name: Fetch SBOMs | |
run: | | |
set -eux | |
mkdir -p sboms/threat-dragon-container-image/app/ | |
cp raw/sboms-server/sbom.json sboms/threat-dragon-server-bom.json | |
cp raw/sboms-server/sbom.xml sboms/threat-dragon-server-bom.xml | |
cp raw/sboms-desktop-windows-site/bom.json sboms/threat-dragon-desktop-windows-site-bom.json | |
cp raw/sboms-desktop-windows-site/bom.xml sboms/threat-dragon-desktop-windows-site-bom.xml | |
cp raw/sboms-desktop-macos-site/bom.json sboms/threat-dragon-desktop-macos-site-bom.json | |
cp raw/sboms-desktop-macos-site/bom.xml sboms/threat-dragon-desktop-macos-site-bom.xml | |
cp raw/sboms-desktop-linux-site/bom.json sboms/threat-dragon-desktop-linux-site-bom.json | |
cp raw/sboms-desktop-linux-site/bom.xml sboms/threat-dragon-desktop-linux-site-bom.xml | |
cp raw/sboms-desktop-linux-snap-site/bom.json sboms/threat-dragon-desktop-linux-snap-site-bom.json | |
cp raw/sboms-desktop-linux-snap-site/bom.xml sboms/threat-dragon-desktop-linux-snap-site-bom.xml | |
cp raw/sboms-container-image-app/* sboms/threat-dragon-container-image/app/ | |
- name: Save SBOM artifact | |
uses: actions/upload-artifact@v4.4.0 | |
with: | |
name: sboms | |
path: 'sboms/' | |
include-hidden-files: true | |
webapp_release: | |
name: Publish web application | |
runs-on: ubuntu-24.04 | |
needs: | |
- desktop_macos | |
- desktop_linux | |
- desktop_windows | |
- sbom_combiner | |
steps: | |
- name: Check out | |
uses: actions/checkout@v4.2.0 | |
- name: Fetch prepared SBOM artifacts | |
uses: actions/download-artifact@v4.1.8 | |
with: | |
name: 'sboms' | |
path: 'sboms/' | |
- name: Prepare release notes | |
run: | | |
releaseVersion=${{ github.ref_name }} | |
sed -e s/2.x.x/${releaseVersion:1}/g .release-note-template.md > ./release-notes.txt | |
tar -czvf threat-dragon-sboms.zip sboms | |
- name: Create release notes | |
uses: softprops/action-gh-release@v2.1.0 | |
with: | |
draft: true | |
name: "${releaseVersion:1}" | |
append_body: true | |
body_path: ./release-notes.txt | |
generate_release_notes: true | |
files: | | |
threat-dragon-sboms.zip |