Skip to content

release

release #1

Workflow file for this run

name: release
on:
push:
# Releases are tags named 'v<version>', and must have the "major.minor.micro", for example: "0.1.0".
# Release candidates are tagged as `v<version>-rc<num>`, for example: "0.1.0-rc1".
tags:
- "v*"
permissions:
contents: write # for creating a release
packages: write # for publishing containers
id-token: write # for using OIDC tokens
env:
SYFT_VERSION: "0.68.1"
jobs:
init:
runs-on: ubuntu-22.04
outputs:
version: ${{steps.version.outputs.version}}
prerelease: ${{steps.state.outputs.prerelease}}
latest: ${{steps.latest.outputs.latest}}
steps:
- name: Evaluate state
id: state
env:
HEAD_REF: ${{github.head_ref}}
run: |
test -z "${HEAD_REF}" && (echo 'do-publish=true' >> $GITHUB_OUTPUT)
if [[ "${{ github.event.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo release=true >> $GITHUB_OUTPUT
elif [[ "${{ github.event.ref }}" =~ ^refs/tags/v.*$ ]]; then
echo prerelease=true >> $GITHUB_OUTPUT
fi
- name: Set version
id: version
run: |
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
[ "$VERSION" == "main" ] && VERSION=latest
echo "Version: $VERSION"
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Set latest
id: latest
# Should evaluate to "true" is this should also be pushed as "latest".
# This should be the case when we push a nightly, assuming that "nightly" tags increment on the main branch.
run: |
LATEST=false
[[ "${{ github.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+-nightly.[0-9a-f]+$ ]] && LATEST=true
echo "Latest: $LATEST"
echo "latest=$LATEST" >> $GITHUB_OUTPUT
# check that our CI would pass
ci:
uses: ./.github/workflows/ci.yaml
# now do the actual (release) builds
build:
needs: [ init, ci ]
strategy:
matrix:
target:
- linux-amd64
#- macos-amd64
#- macos-aarch64
#- windows-amd64
include:
- target: linux-amd64
os: ubuntu-22.04
#- target: macos-amd64
# os: macos-12
#- target: macos-aarch64
# os: macos-12
# rustTarget: "aarch64-apple-darwin"
# xcode: "true"
#- target: windows-amd64
# os: windows-2022
# exe: ".exe"
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/.crates.toml
~/.cargo/.crates2.json
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ matrix.target }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install cargo binstall
run: |
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
- name: Install trunk
run: cargo binstall -y trunk
- name: Install additional targets target
run: |
rustup target add wasm32-unknown-unknown
rustup target add aarch64-apple-darwin
- name: Install Protoc
uses: arduino/setup-protoc@v2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install cargo-auditable
run: cargo binstall -y cargo-auditable
- name: Build
shell: bash
run: |
if [[ "${{ matrix.xcode }}" == "true" ]]; then
TAG=${{ needs.init.outputs.version }} SDKROOT=$(xcrun -sdk macosx --show-sdk-path) MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx --show-sdk-platform-version) cargo auditable build --target=${{ matrix.rustTarget }} -p trust --release
else
TAG=${{ needs.init.outputs.version }} cargo auditable build --release -p trust
fi
- name: List output
shell: bash
run: ls -l target/release/
- name: Rename binary
shell: bash
run: cp -pv target/${{ matrix.rustTarget }}/release/trust${{ matrix.exe }} target/release/trust-${{ matrix.target }}${{ matrix.exe }}
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: trust-binary-${{ matrix.target }}
path: target/release/trust-${{ matrix.target }}${{ matrix.exe }}
if-no-files-found: error
publish:
needs: [ init, build ]
permissions:
contents: write
packages: write
id-token: write # for using OIDC tokens
runs-on: ubuntu-22.04
env:
CONTAINERS: "trust trust-docs trust-tests"
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
# cache cargo data, not because of the build, but because of cargo based tooling
- uses: actions/cache@v3
with:
path: |
~/.cargo/bin/
~/.cargo/.crates.toml
~/.cargo/.crates2.json
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
# although we don't use anything from the Cargo project, we still keep hashing the .lock file to get some
# id that aligns with the project
key: ${{ runner.os }}-cargo-publish-${{ hashFiles('**/Cargo.lock') }}
- name: Install cyclonedx cli
run: |
curl -sLO https://github.com/CycloneDX/cyclonedx-cli/releases/download/v0.24.2/cyclonedx-linux-x64
sudo install cyclonedx-linux-x64 /usr/local/bin/cyclonedx
cyclonedx --version
- name: Install convco
run: |
curl -sLO https://github.com/convco/convco/releases/download/v0.4.0/convco-ubuntu.zip
unzip convco-ubuntu.zip
chmod a+x convco
sudo mv convco /usr/local/bin
- name: Install cargo binstall
run: |
curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
- name: Fetch syft binary
run: |
curl -sL "https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/syft_${SYFT_VERSION}_linux_amd64.tar.gz" -o syft.tar.gz
tar xzf syft.tar.gz
chmod a+x syft
sudo mv syft /usr/local/bin
- name: Install cosign
uses: sigstore/cosign-installer@v2
- name: Check cosign
run: cosign version
- name: Generate changelog
run: |
convco changelog -s --max-majors=1 --max-minors=1 --max-patches=1 > /tmp/changelog.md
- uses: actions/download-artifact@v4
with:
path: ~/download
- name: Display downloaded content
run: ls -R ~/download
- name: Stage release
run: |
mkdir -p staging
cp -pv ~/download/*/trust-* staging/
- name: Install nodejs dependencies
run: |
cd spog/ui
npm ci
- name: Create SBOM of the cargo projects
# gather dependencies from cargo auditable build
run: |
cargo binstall -y cargo-cyclonedx
cargo cyclonedx --all --format json
cp trust/bom.json staging/trust.project.sbom.json
- name: Create SBOM of the frontend
# gather (embedded) dependencies from the yarn build
run: |
syft spog/ui/package-lock.json --output cyclonedx-json > staging/trust-ui.project.sbom.json
- name: Merge project SBOM
# merge both SBOMs
run: |
cyclonedx merge \
--input-files \
staging/trust.project.sbom.json \
staging/trust-ui.project.sbom.json \
--output-file staging/project.sbom.json
- name: Create SBOMs for binaries
# this step will create SBOMs for binaries, based on the information embedded by `cargo auditable build`
# and amend the information with the frontend project SBOM
run: |
for i in $(ls staging/trust*); do
syft ${i} --output cyclonedx-json > ${i}.sbom.cargo-auditable.json
cyclonedx merge --input-files ${i}.sbom.cargo-auditable.json staging/trust-ui.project.sbom.json --output-file ${i}.sbom.json
done
- name: Cosign blobs
env:
COSIGN_EXPERIMENTAL: "1"
run: |
for i in $(ls staging/trust*); do
cosign sign-blob --yes --b64=false ${i} --output-signature ${i}.cosign.sig --output-certificate ${i}.cosign.crt
done
- name: Generate container SBOM
run: |
for container in $CONTAINERS; do
syft ~/download/${container}-container/${container}-image.tar --output cyclonedx-json --catalogers rpm,cargo-auditable > staging/${container}.sbom.json
cyclonedx merge --input-files staging/${container}.sbom.json staging/trust-ui.project.sbom.json --output-file staging/${container}.sbom.json
done
- name: Load container
run: |
for container in $CONTAINERS; do
podman load --input ~/download/${container}-container/${container}-image.tar
done
- name: Log in to ghcr.io
uses: redhat-actions/podman-login@v1
with:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
registry: "ghcr.io"
- name: Push to ghcr.io
id: push-images
run: |
for container in $CONTAINERS; do
IMAGE="ghcr.io/${{ github.repository_owner }}/${container}:${{ needs.init.outputs.version }}"
podman push \
"${container}:ci" \
"${IMAGE}" \
--digestfile "${RUNNER_TEMP}/push.${container}.digest"
done
- name: Push to ghcr.io (as latest)
if: ${{ needs.init.outputs.latest == 'true' }}
id: push-images-latest
run: |
for container in $CONTAINERS; do
IMAGE="ghcr.io/${{ github.repository_owner }}/${container}:latest"
podman push \
"${container}:ci" \
"${IMAGE}"
done
- name: Sign the images with GitHub OIDC Token
env:
COSIGN_EXPERIMENTAL: true
run: |
for container in $CONTAINERS; do
imageDigest="$(cat ${RUNNER_TEMP}/push.${container}.digest)"
echo "Image Digest: ${imageDigest}"
# and then construct the full (pushed) name
cosign sign --yes --recursive "ghcr.io/${{ github.repository_owner }}/${container}@${imageDigest}"
done
- name: Attach container SBOM information
env:
COSIGN_EXPERIMENTAL: true
run: |
for container in $CONTAINERS; do
IMAGE="ghcr.io/${{ github.repository_owner }}/${container}:${{ needs.init.outputs.version }}"
# attach and sign SBOM
cosign attach sbom --sbom staging/${container}.sbom.json --input-format json --type cyclonedx ${IMAGE}
cosign sign --attachment sbom ${IMAGE}
# attach SBOM as attestation
cosign attest --yes --recursive --type cyclonedx --predicate staging/${container}.sbom.json ${IMAGE}
done
- run: |
for container in $CONTAINERS; do
cp ~/download/${container}-container/${container}-image.tar staging/${container}-container.tar
xz staging/${container}-container.tar
done
- name: Display staging area
run: ls -R staging
- name: Create Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG: v${{ needs.init.outputs.version }}
run: |
OPTS=""
if [[ "${{ needs.init.outputs.prerelease }}" == "true" ]]; then
OPTS="${OPTS} -p"
fi
gh release create ${OPTS} --title "${{ needs.init.outputs.version }}" -F /tmp/changelog.md ${TAG} \
$(find staging -type f)
staging:
needs: [ init, publish ]
uses: ./.github/workflows/staging.yaml
secrets: inherit
with:
releaseTag: ${{ needs.init.outputs.version }}