Skip to content
Merged
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
96 changes: 72 additions & 24 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ on:
push:
tags:
- 'v*.*.*'
# A change to this file runs the build and SBOM jobs on its PR, so a broken
# release path shows up at review rather than at the next tag. The release
# job is skipped on PRs.
pull_request:
paths:
- '.github/workflows/release.yml'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., v0.1.0)'
description: 'Existing tag to release (e.g., v0.1.0). The build checks out this tag.'
required: true
permissions:
contents: write
id-token: write
contents: read
jobs:
build:
name: Build Package
Expand All @@ -21,15 +26,32 @@ jobs:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
julia-version: ['1.10']
defaults:
run:
shell: bash
steps:
# On a manual run, build the tag being released, not the default branch,
# so the artefacts match the tagged and registered tree. The ref is
# qualified as refs/tags/: checkout resolves a bare name to a branch of
# that name before a tag (src/ref-helper.ts). On other events
# inputs.version is empty, ref is empty, and checkout uses the triggering ref.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.version && format('refs/tags/{0}', inputs.version) || '' }}
- uses: julia-actions/setup-julia@fa02766e078afaaf09b14210362cee14137e6a32 # v3.0.2
with:
version: ${{ matrix.julia-version }}
- uses: julia-actions/cache@e32267b41e0fa7df82a3d53e8c7273620d52c586 # v3.4.0
# A library release is tested the way users install it: resolved fresh
# from Project.toml [compat].
- name: Ignore any committed manifest
run: rm -f Manifest.toml
# AcceleratorGate is registered in the hyperpolymath registry, not in
# General.
- name: Add registries
run: julia -e 'using Pkg; Pkg.Registry.add("General"); Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/hyperpolymath/julia-professional-registry"))'
- name: Build and test
run: |
julia --project -e 'using Pkg; Pkg.build(); Pkg.test()'
run: julia --project -e 'using Pkg; Pkg.build(); Pkg.test()'
- name: Package artifacts
run: |
mkdir -p dist
Expand All @@ -46,15 +68,32 @@ jobs:
needs: build
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
with:
ref: ${{ inputs.version && format('refs/tags/{0}', inputs.version) || '' }}
- uses: julia-actions/setup-julia@fa02766e078afaaf09b14210362cee14137e6a32 # v3.0.2
with:
version: '1.10'
# Pkg.dependencies() needs a resolved environment. JSON is not a
# dependency of this package, so it is loaded from a throwaway
# environment after the component list has been read.
- name: Generate SBOM
run: |
rm -f Manifest.toml
julia -e 'using Pkg; Pkg.Registry.add("General"); Pkg.Registry.add(Pkg.RegistrySpec(url="https://github.com/hyperpolymath/julia-professional-registry"))'
julia --project -e '
using Pkg, JSON
using Pkg
Pkg.instantiate()
pkg_info = Pkg.project()
deps = Pkg.dependencies()
components = [
Dict(
"type" => "library",
"name" => info.name,
"version" => info.version === nothing ? "stdlib" : string(info.version)
) for (uuid, info) in Pkg.dependencies() if info.is_direct_dep
]
Pkg.activate(temp=true)
Pkg.add("JSON")
using JSON
sbom = Dict(
"bomFormat" => "CycloneDX",
"specVersion" => "1.4",
Expand All @@ -66,13 +105,7 @@ jobs:
"version" => string(pkg_info.version)
)
),
"components" => [
Dict(
"type" => "library",
"name" => string(uuid),
"version" => string(info.version)
) for (uuid, info) in deps if info.is_direct_dep
]
"components" => components
)
open("sbom.json", "w") do f
JSON.print(f, sbom, 2)
Expand All @@ -85,6 +118,7 @@ jobs:
path: sbom.json
release:
name: Create Release
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 15
needs: [build, sbom]
Expand All @@ -93,7 +127,28 @@ jobs:
id-token: write
attestations: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4
# Refuse anything but an existing vX.Y.Z tag, so a mistyped manual run
# cannot make action-gh-release create a new tag on the default branch.
- name: Extract version
id: version
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_VERSION: ${{ inputs.version }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
version="$INPUT_VERSION"
else
version="${GITHUB_REF#refs/tags/}"
fi
if ! printf '%s\n' "$version" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "::error::the version to release is not of the form vX.Y.Z"
exit 1
fi
if ! git ls-remote --exit-code --tags "$GITHUB_SERVER_URL/$GITHUB_REPOSITORY" "refs/tags/$version" > /dev/null; then
echo "::error::tag $version does not exist; push the tag first"
exit 1
fi
echo "version=$version" >> "$GITHUB_OUTPUT"
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
Expand All @@ -103,19 +158,11 @@ jobs:
mkdir -p release
find release-artifacts -type f -exec cp {} release/ \;
cd release
sha256sum * > checksums.txt
sha256sum -- * > checksums.txt
- name: Attest build provenance
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: 'release/*'
- name: Extract version
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
echo "version=${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT
else
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
fi
- name: Create GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v2
with:
Expand All @@ -133,6 +180,7 @@ jobs:

```bash
sha256sum -c checksums.txt
gh attestation verify <file> -R hyperpolymath/SMTLib.jl
```
files: release/*
draft: false
Expand Down
Loading