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
5 changes: 4 additions & 1 deletion .envrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

# Activate the default devShell
use flake

# create the venv if it doesn't yet exist
# Create the venv if it doesn't yet exist, and update the project's environment
# with all useful dependencies that can be run under the nix environment
[[ -d ".venv" ]] || (uv venv && uv sync --extra=nix)

# Activate the project venv
. .venv/bin/activate
40 changes: 40 additions & 0 deletions .github/actions/lowrisc_ci_app_get_token.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

# NOTE.
# Requires id-token: write in the workflow to get the JWT

name: Get lowrisc-ci app access token
description: Obtain a lowrisc-ci GitHub App installation access token from the lowRISC CA

inputs:
audience:
description: intended audience for the requested JWT
type: string
default: "https://ca.lowrisc.org"
ca_api_endpoint:
description: lowRISC CA endpoint from which to try and obtain a token.
type: string
default: "https://ca.lowrisc.org/api/github/repos/${{ github.repository }}/token"

runs:
using: "composite"
steps:
- name: Get and exchange tokens
id: get_token
run: |
# First, manually request a JSON Web Token (JWT) from GitHub's OIDC provider for the workflow
# - Set our CA as the intended audience
ID_TOKEN=$(curl -sSf -H "Authorization: Bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN" "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=${{ inputs.audience }}" | jq -r .value)
echo "::add-mask::$ID_TOKEN"
# Now use the JWT token to request the lowRISC CA to provide an lowrisc-ci app installation access token suitable for our action
ACCESS_TOKEN=$(curl -sSf -X POST -H "Authorization: Bearer $ID_TOKEN" ${{ inputs.ca_api_endpoint }})
echo "::add-mask::$ACCESS_TOKEN
echo "token=$ACCESS_TOKEN" >> "$GITHUB_OUTPUT"

outputs:
token:
description: "Token"
value: ${{ steps.get_token.outputs.token }}

3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

name: Python application
name: CI checks

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
merge_group:

permissions:
contents: read
Expand Down
182 changes: 172 additions & 10 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,193 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

name: DVSim Release
# Create a dvsim semantic-release according to conventional-commit directives in changeset
name: Create a dvsim release

on:
push:
branches:
- master
# Branch-protected, only reviewed pull-requests push to master
- "master"

permissions:
contents: write
contents: read

jobs:

release:
name: Tag a new semantic-release and push
runs-on: ubuntu-latest
permissions:
# Push release commit / tag
contents: write
# This is required for requesting the JWT for 'lowrisc_ci_app_get_token.yml'
id-token: write

steps:
- name: Repository checkout

- name: Get an installation access token for the lowrisc-ci app with appropriate permissions
id: get-token
uses: ./.github/actions/lowrisc_ci_app_get_token.yml

- name: Setup | Checkout Repository at PR branch
uses: actions/checkout@v4
with:
token: ${{ steps.get-token.outputs.token }}
ref: ${{ github.ref_name }}
# Full-depth needed for semantic-release to determine version and changelog
fetch-depth: 0

- name: Install python-semantic-release package
run: python3 -m pip install python-semantic-release
- name: Setup | Install uv
uses: astral-sh/setup-uv@v6

- name: Setup | Install Python + the python project with release dependencies
run: |
uv sync --extra release

- name: Versioning and Publishing the release
# Create new release commit that updates CHANGELOG, version strings, creates tag
# Push new commit / tag to remote
# Do not build, that will be done in the next step by invoking uv directly
- name: Release | Create new release metadata, push commit/tag
id: version_release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GH_TOKEN: ${{ steps.get-token.outputs.token }}
run: |
# First time round, just determine the new version and increment the pyproject.toml accordingly.
# Then, we can re-lock uv.lock with the new version, and leave the change staged
uv run semantic-release version --skip-build --no-changelog --no-commit --no-tag --no-push --no-vcs-release
uv lock --upgrade-package 'dvsim'
git add uv.lock
# The second invocation generates all other release metadata, and wraps up the lockfile change
# into the single tagged release commit
uv run semantic-release version --skip-build

- name: Release | Print if not required
if: ${{ steps.version_release.outputs.released == 'false' }}
run: |
echo "### Release Summary - dvsim" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "New release not required as per commits since last release. :ok:" >> $GITHUB_STEP_SUMMARY
# TODO - Add hyperlinks to project documentation for users who were expecting a new release now...

# Forward some outputs from 'semantic-release version' so that subsequent jobs
# can be conditionally run only if a new released has actually been generated.
outputs:
released: ${{ steps.version_release.outputs.released }}
tag: ${{ steps.version_release.outputs.tag }}

###################
# DEPLOYMENT JOBS #
###################
# 1. Separate out the deploy step from the release step to run each step at
# the least amount of token privilege
# 2. Also, deployments can fail, and its better to have a separate job if you need to retry
# and it won't require reversing the release.

build_release_artifacts:
name: Build dist release artifacts, push src + dist assets to GitHub release
needs: release
if: ${{ needs.release.outputs.released == 'true' }}
runs-on: ubuntu-latest
permissions:
# Upload github release artifacts
contents: write

steps:

- name: Setup | Checkout Repository at newly tagged release
uses: actions/checkout@v4
with:
# Can't checkout at the new tag, we need to match one of the configured
# semantic_release.branches for the publish-action to proceed.
# > Detached HEAD state cannot match any release groups; no release will be made
ref: ${{ github.ref_name }}
# Also need the tags for the publish step to work
fetch-tags: true

- name: Setup | Install uv
uses: astral-sh/setup-uv@v6

- name: Setup | Install Python + the python project with build dependencies
run: |
uv sync

# Build the newly-versioned release distribution
- name: Release | Build the release
id: build_release
run: |
semantic-release version --no-changelog
semantic-release publish
uv build

- name: Publish | Create GitHub Release (src + dist)
uses: python-semantic-release/[email protected]
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ needs.release.outputs.tag }}

- name: Upload | Distribution artifacts to blob store for follow-up jobs
uses: actions/upload-artifact@v4
with:
name: distribution-artifacts
path: dist
if-no-files-found: error

- name: Release | Print to summary
run: |
echo "### Release Summary - dvsim" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "New release ${{ needs.release.outputs.tag }} cut and deployed. :airplane:" >> $GITHUB_STEP_SUMMARY

test-pypi-publish:
name: Upload release to test.pypi
needs: build_release_artifacts
runs-on: ubuntu-latest
environment:
name: test.pypi
url: https://test.pypi.org/p/dvsim
permissions:
# IMPORTANT: this permission is mandatory for Trusted Publishing
id-token: write

steps:

- name: Setup | Download dist artifacts from previous job
uses: actions/download-artifact@v4
id: artifact-download
with:
name: distribution-artifacts
path: dist

- name: Publish | Package distribution to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
packages-dir: dist
print-hash: true
verbose: true

pypi-publish:
name: Upload release to pypi
needs: build_release_artifacts
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/dvsim
permissions:
# IMPORTANT: this permission is mandatory for Trusted Publishing
id-token: write

steps:

- name: Setup | Download dist artifacts from previous job
uses: actions/download-artifact@v4
id: artifact-download
with:
name: distribution-artifacts
path: dist

- name: Publish | Package distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist
print-hash: true
verbose: true
2 changes: 2 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@
pkgs-unstable.ruff
pkgs.pyright
pkgs.reuse
# 'act' allows running your GitHub Actions locally for test and development.
pkgs.act
];
env = {
# Prevent uv from managing Python downloads
Expand Down
34 changes: 29 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

###########
# PROJECT #
###########

[project]
name = "dvsim"
version = "0.1.0"
description = "DV system"
authors = [{name = "lowRISC contributors (OpenTitan project)"}]
readme = "README.md"
licence = "Apache-2.0"
license-files = ["LICENSE"]
requires-python = ">=3.10"
dependencies = [
# Keep sorted
"click>=8.1.7",
Expand All @@ -22,7 +28,6 @@ dependencies = [
"tabulate>=0.9.0",
"toml>=0.10.2",
]
requires-python = ">=3.10"

[project.optional-dependencies]
typing = [
Expand All @@ -39,13 +44,19 @@ test = [
"pytest>=8.3.3",
"pytest-cov>=5.0.0",
]
dev = ["dvsim[linting,typing,test,debug]"]
release = [
"python-semantic-release>=10.4.1",
]

dev = [
"dvsim[linting,typing,test,debug]"
]
ci = [
"dvsim[linting,typing,test]",
"gitpython",
]

# drop out ruff as it contains a rust binary that needs to be installed by the flake
# Dependency set to be installed automatically in the direnv-activated nix devshell
# - Leave out ruff(linting) as it contains a rust binary that needs to be installed by the flake
nix = [
"dvsim[typing,test,debug]",
"gitpython",
Expand All @@ -54,10 +65,18 @@ nix = [
[project.scripts]
dvsim = "dvsim.cli:main"

################
# BUILD-SYSTEM #
################

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

########
# TOOL #
########

[tool.hatch]
metadata.allow-direct-references = true

Expand Down Expand Up @@ -108,7 +127,8 @@ norecursedirs = ["*.egg", ".*", "_darcs", "build", "dist", "venv", "scratch", "d
[tool.semantic_release]
commit_parser = "conventional"
version_toml = ["pyproject.toml:project.version"]
commit_message = "Bump v{version}"
commit_author = "semantic-release <[email protected]>"
commit_message = "Bump version to v{version}"

[tool.semantic_release.commit_parser_options]
minor_tags = ["feat"]
Expand All @@ -120,3 +140,7 @@ ignore_merge_commits = true
match = "master"
prerelease_token = "rc"
prerelease = false

[tool.semantic_release.remote]
name = "origin"
ignore_token_for_push = true
1 change: 1 addition & 0 deletions scripts/license_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"LICENSE",
"NOTICE",
".python-version",
"CHANGELOG.md",
]

IGNORE_SUFFIXES = [".lock"]
Expand Down
Loading
Loading