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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/01_bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ body:
id: rustiq_version
attributes:
label: RustiQ version or commit
placeholder: v0.1.0-alpha.1 or commit SHA
placeholder: v0.1.0-beta.1 or commit SHA
validations:
required: true

Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,27 @@ jobs:
if: matrix.os == 'windows-latest' && matrix.python-version == '3.12'
run: uv run --locked --python ${{ matrix.python-version }} pytest tools/reference/test_persistence_interop.py -k reads_rust

pyscf-native:
name: PySCF reference suite (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-15-intel, macos-latest, windows-latest]
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up uv
uses: astral-sh/setup-uv@68559e99cc807c1eb7e9238fd43a15bba460eec2 # v10.3.3
with:
python-version: '3.12'
- name: Install Rust stable
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c # stable
- name: Cache Rust builds
uses: Swatinem/rust-cache@d1527c8f67ef9af357290475d4af4b0fab8f12e0 # v2.9.3
- name: Run PySCF comparisons
run: uv run --locked pytest tools/reference

nix:
name: Nix flake (${{ matrix.system }})
runs-on: ${{ matrix.os }}
Expand Down
231 changes: 159 additions & 72 deletions .github/workflows/release-smoke.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
name: Release artifact smoke test

on:
pull_request:
branches: [main]
workflow_dispatch:
inputs:
ref:
Expand All @@ -12,13 +14,17 @@ on:
permissions:
contents: read

concurrency:
group: release-smoke-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
manual:
uses: ./.github/workflows/build-release-manual.yml
with:
ref: ${{ inputs.ref }}

smoke:
build:
needs: manual
name: ${{ matrix.target }}
strategy:
Expand All @@ -32,7 +38,7 @@ jobs:
- target: x86_64-apple-darwin
runner: macos-15-intel
- target: aarch64-apple-darwin
runner: macos-14
runner: macos-latest
- target: x86_64-pc-windows-msvc
runner: windows-2025
- target: aarch64-pc-windows-msvc
Expand Down Expand Up @@ -120,93 +126,174 @@ jobs:
python -m json.tool dist-manifest.json > /dev/null
python -c 'import json; from pathlib import Path; files=json.loads(Path("dist-manifest.json").read_text())["upload_files"]; assert isinstance(files, list) and files, "dist manifest has no upload_files"'
mkdir -p target/distrib
cp dist-manifest.json target/distrib/dist-manifest.json
cp dist-manifest.json "target/distrib/${{ matrix.target }}-dist-manifest.json"

- name: Upload distributable packages
id: packages
if: success()
uses: actions/upload-artifact@v7.0.2
with:
name: rustiq-packages-${{ matrix.target }}
path: |
target/distrib/*.tar.gz
target/distrib/*.zip
target/distrib/*.sha256
target/distrib/sha256.sum
target/distrib/*-dist-manifest.json
if-no-files-found: error

- id: validate
name: Validate archive and run H2 calculation
- name: Link downloadable packages
if: steps.packages.outcome == 'success'
shell: bash
env:
PACKAGE_URL: ${{ steps.packages.outputs.artifact-url }}
TARGET: ${{ matrix.target }}
run: |
printf '[Download packages for %s](%s) (archive and checksums)\n' "$TARGET" "$PACKAGE_URL" >> "$GITHUB_STEP_SUMMARY"

- name: Upload archive, manifest, and diagnostic logs
if: always()
uses: actions/upload-artifact@v7.0.2
with:
name: release-build-${{ matrix.target }}
path: |
target/distrib/**
dist-manifest.json
dist-build.log
validation.log
release-smoke-logs/**
if-no-files-found: warn

global:
name: Assemble release packages with dist
needs: build
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v7
with:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false

- uses: dtolnay/rust-toolchain@stable

- name: Install configured dist version
shell: bash
run: |
set -euo pipefail
DIST_VERSION="$(python3 -c 'import re; from pathlib import Path; print(re.search(r"cargo-dist-version\s*=\s*\"([^\"]+)\"", Path("dist-workspace.toml").read_text()).group(1))')"
curl --proto '=https' --tlsv1.2 -LsSf "https://github.com/axodotdev/cargo-dist/releases/download/v${DIST_VERSION}/cargo-dist-installer.sh" | sh

- name: Download native packages
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: rustiq-packages-*
path: target/distrib
merge-multiple: true

- name: Build global release assets
shell: bash
run: |
set -euo pipefail
python - <<'PY' 2>&1 | tee validation.log
import json
dist build --artifacts=global --output-format=json > dist-manifest.json
dist print-upload-files-from-manifest --manifest dist-manifest.json > global-upload-files.txt
mkdir -p release-packages
cp target/distrib/*.tar.gz target/distrib/*.zip target/distrib/*.sha256 release-packages/
while IFS= read -r asset; do
cp "$asset" release-packages/
done < global-upload-files.txt

- name: Upload complete release packages
id: release
uses: actions/upload-artifact@v7.0.2
with:
name: rustiq-release-packages
path: release-packages/*
if-no-files-found: error

- name: Link complete release download
env:
PACKAGE_URL: ${{ steps.release.outputs.artifact-url }}
run: |
printf '[Download all release packages](%s) — native archives, checksums, and corresponding source.\n' "$PACKAGE_URL" >> "$GITHUB_STEP_SUMMARY"

smoke:
name: Smoke final packages (${{ matrix.target }})
needs: global
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: ubuntu-22.04
- target: aarch64-unknown-linux-gnu
runner: ubuntu-24.04-arm
- target: x86_64-apple-darwin
runner: macos-15-intel
- target: aarch64-apple-darwin
runner: macos-latest
- target: x86_64-pc-windows-msvc
runner: windows-2025
- target: aarch64-pc-windows-msvc
runner: windows-11-arm
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ inputs.ref || github.sha }}
persist-credentials: false

- name: Download final release packages
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
name: rustiq-release-packages
path: release-packages

- name: Validate final archive and run H2 calculation
shell: bash
env:
TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
python - <<'PYTHON' 2>&1 | tee validation.log
import os
import subprocess
import sys
from pathlib import Path
manifest = json.loads(Path("target/distrib/dist-manifest.json").read_text())
paths = [Path(p) for p in manifest["upload_files"]]
archives = [p for p in paths if p.suffix.lower() in {".zip", ".gz"} and "rustiq" in p.name.lower()]

root = Path("release-packages")
target = os.environ["TARGET"]
suffix = ".zip" if "windows" in target else ".tar.gz"
archives = list(root.glob(f"*-{target}{suffix}"))
if len(archives) != 1:
raise SystemExit(f"MISSING_ARCHIVE: expected one RustiQ archive in dist manifest, got {archives}")
archive = archives[0]
checksum = Path(str(archive) + ".sha256")
if not checksum.exists():
checksum = archive.parent / "sha256.sum"
if not checksum.exists():
raise SystemExit(f"CHECKSUM_FAILURE: no checksum sidecar or sha256.sum for {archive}")
import subprocess, sys
command = [sys.executable, "tools/release_smoke.py", str(archive), "--fixture", "tests/data/sto-3g.json", "--geometry", "samples/h2/molecule.xyz", "--reference-source", "crates/rustiq-core/src/hf/scf.rs", "--logs", "release-smoke-logs"]
command += ["--checksum", str(checksum)]
subprocess.run(command, check=True)
print(f"::notice title=Archive::{archive.name}")
PY

- name: Report target result
raise SystemExit(f"MISSING_ARCHIVE: expected one archive for {target}, got {archives}")
checksum = root / "sha256.sum"
if not checksum.is_file():
raise SystemExit("CHECKSUM_FAILURE: final release has no sha256.sum")
subprocess.run([
sys.executable, "tools/release_smoke.py", str(archives[0]),
"--checksum", str(checksum),
"--fixture", "tests/data/sto-3g.json",
"--geometry", "samples/h2/molecule.xyz",
"--reference-source", "crates/rustiq-core/src/hf/scf.rs",
"--logs", "release-smoke-logs",
], check=True)
PYTHON

- name: Report final package result
if: always()
shell: bash
env:
TARGET: ${{ matrix.target }}
INSTALL_UNIX: ${{ steps.install_unix.outcome }}
INSTALL_WINDOWS_X64: ${{ steps.install_windows_x64.outcome }}
INSTALL_WINDOWS_ARM64: ${{ steps.install_windows_arm64.outcome }}
DIST_VERSION_RESULT: ${{ steps.verify_dist.outcome }}
BUILD_RESULT: ${{ steps.build.outcome }}
VALIDATION_RESULT: ${{ steps.validate.outcome }}
RESULT: ${{ job.status }}
run: |
case "$TARGET" in
*windows*) archive="rustiq-chem-$TARGET.zip" ;;
*) archive="rustiq-chem-$TARGET.tar.gz" ;;
esac
stage=""
if [[ "$VALIDATION_RESULT" == success ]]; then
checksum=verified; startup=passed; manual=passed; h2="RHF regression check passed"; status=PASS
else
checksum="not confirmed"; startup="not confirmed"; manual="not confirmed"; h2="not confirmed"; status=FAIL
if [[ "$INSTALL_UNIX" == failure || "$INSTALL_WINDOWS_X64" == failure || "$INSTALL_WINDOWS_ARM64" == failure ]]; then
stage="dist installation failure"; archive="not produced"
elif [[ "$DIST_VERSION_RESULT" == failure ]]; then
stage="dist version verification failure"; archive="not produced"
elif [[ "$BUILD_RESULT" == failure ]]; then
stage="archive build failure"; archive="not produced"
elif [[ "$BUILD_RESULT" == skipped ]]; then
stage="setup or prerequisite failure"; archive="not produced"
elif grep -q 'MISSING_ARCHIVE' validation.log 2>/dev/null; then stage="missing archive"
elif grep -q 'CHECKSUM_FAILURE' validation.log 2>/dev/null; then stage="checksum failure"
elif grep -q 'EXTRACTION_FAILURE' validation.log 2>/dev/null; then stage="extraction failure"
elif grep -q 'EXECUTABLE_STARTUP_FAILURE' validation.log 2>/dev/null; then stage="executable startup failure"
elif grep -q 'DOCUMENTATION_FAILURE' validation.log 2>/dev/null; then stage="offline manual failure"
elif grep -q 'SCIENTIFIC_CALCULATION_FAILURE' validation.log 2>/dev/null; then stage="scientific calculation failure"
elif grep -q 'JSON_VALIDATION_FAILURE' validation.log 2>/dev/null; then stage="JSON validation failure"
else stage="validation failure (inspect validation.log)"
fi
fi
{
printf '## Release rehearsal: %s\n\n' "$TARGET"
echo '| Target | Archive | Checksum | Executable startup | Offline manual | H2 calculation | Final status |'
echo '|---|---|---|---|---|---|---|'
printf '| `%s` | `%s` | %s | %s | %s | %s | **%s** |\n' "$TARGET" "$archive" "$checksum" "$startup" "$manual" "$h2" "$status"
if [[ "$status" == FAIL ]]; then printf '\nFailed stage: %s\n' "$stage"; fi
echo
echo "Built and tested on a GitHub-hosted native runner. This is not a pristine OS image."
} >> "$GITHUB_STEP_SUMMARY"
[[ "$VALIDATION_RESULT" == success ]]
printf 'Final release package smoke test: `%s` — **%s**\n' "$TARGET" "$RESULT" >> "$GITHUB_STEP_SUMMARY"

- name: Upload archive, manifest, and diagnostic logs
- name: Upload smoke diagnostics
if: always()
uses: actions/upload-artifact@v7.0.2
with:
name: release-smoke-${{ matrix.target }}
path: |
target/distrib/**
dist-manifest.json
dist-build.log
validation.log
release-smoke-logs/**
if-no-files-found: warn
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ jobs:

# Build and packages all the platform-specific things
build-local-artifacts:
name: build-local-artifacts (${{ join(matrix.targets, ', ') }})
name: Build platform artifacts
# Let the initial task tell us to not run (currently very blunt)
needs:
- plan
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/scientific-report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ jobs:
- name: Run selected ERI Criterion benchmarks
id: eri
continue-on-error: true
run: cargo bench --features bench-support --bench eri_timings
run: cargo bench --features bench --bench eri_timings

- name: Run selected MP2 Criterion benchmarks
id: mp2
continue-on-error: true
run: cargo bench --features bench-support --bench mp2_timings
run: cargo bench --features bench --bench mp2_timings

- name: Generate performance report
id: performance
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

The following capabilities are intended for the first public beta, `v0.1.0-beta.1`.
## [0.1.0-beta.1] - 2026-11-12


### Added

Expand Down Expand Up @@ -58,4 +59,5 @@ The following capabilities are intended for the first public beta, `v0.1.0-beta.
- The MP2 workspace budget does not bound total process memory; AO integral
storage can still grow rapidly with basis size.

[Unreleased]: https://github.com/mveril/RustiQ/commits/main/
[Unreleased]: https://github.com/mveril/RustiQ/compare/v0.1.0-beta.1...HEAD
[0.1.0-beta.1]: https://github.com/mveril/RustiQ/releases/tag/v0.1.0-beta.1
8 changes: 5 additions & 3 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ type: software
authors:
- family-names: Veril
given-names: Mickael
version: 0.1.0-alpha.1
license: MIT OR Apache-2.0
version: 0.1.0-beta.1
license:
- MIT
- Apache-2.0
repository-code: https://github.com/mveril/RustiQ
abstract: A Rust prototype for modern quantum chemistry software.
abstract: Experimental quantum chemistry software written in Rust, providing a reusable scientific library and CLI. RustiQ-authored code is available under MIT OR Apache-2.0.
5 changes: 3 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading