Skip to content

Commit 97fb81e

Browse files
committed
Merge remote-tracking branch 'upstream/dev' into state_recording
2 parents 04afc8f + 30d924d commit 97fb81e

File tree

13 files changed

+1140
-51
lines changed

13 files changed

+1140
-51
lines changed

.coveragerc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ omit =
55

66
[paths]
77
source =
8-
src/
8+
# running from pytribeam root on an offline machine
9+
src
10+
# full path to 'pytribeam/src' on a laser system
911
C:/Users/User/Desktop/Polonsky/____SOFTWARE/pytribeam/src
12+
# full path to `pytribeam/src` on a different laser system
1013
C:/Users/User/Documents/pytribeam/src
14+
C:/Users/apolon/Codebases/pytribeam/src

.github/workflows/_dep_publish.txt

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<<<<<<< HEAD
2+
name: Package
3+
on:
4+
pull_request:
5+
branches: main
6+
release:
7+
types: published
8+
jobs:
9+
Source:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
- name: Python
15+
uses: actions/setup-python@v5
16+
with:
17+
python-version: 3.12
18+
- name: Requirements
19+
run: pip install --upgrade build pip twine
20+
- name: Build
21+
run: python -m build .
22+
- name: Check
23+
run: twine check dist/*
24+
- uses: actions/upload-artifact@v4
25+
with:
26+
name: dist
27+
path: dist
28+
#Wheel:
29+
# strategy:
30+
# fail-fast: false
31+
# matrix:
32+
# os: [macos-latest, ubuntu-latest, windows-latest]
33+
# runs-on: ${{ matrix.os }}
34+
# steps:
35+
# - name: Checkout
36+
# uses: actions/checkout@v4
37+
# - name: Python
38+
# uses: actions/setup-python@v5
39+
# with:
40+
# python-version: 3.12
41+
# - name: Requirements
42+
# run: pip install --upgrade build pip twine
43+
# - name: Wheel
44+
# run: python -m build . --wheel
45+
# - name: Check
46+
# run: twine check dist/*
47+
# - uses: actions/upload-artifact@v4
48+
# with:
49+
# name: ${{ matrix.os }}-dist
50+
# path: dist
51+
Twine:
52+
# needs: [Source, Wheel]
53+
needs: Source
54+
runs-on: ubuntu-latest
55+
steps:
56+
- uses: actions/download-artifact@v4
57+
- uses: actions/setup-python@v5
58+
with:
59+
check-latest: true
60+
python-version: 3.12
61+
- name: Requirements
62+
run: pip install --upgrade pip twine
63+
- name: Upload
64+
if: github.event_name == 'release'
65+
run: twine upload -u __token__ -p ${{ secrets.PYPI_TOKEN }} dist/*
66+
=======
67+
name: Publish to PyPI
68+
69+
on:
70+
push:
71+
branches:
72+
- main # Triggers when push/merge to the 'main' branch
73+
tags:
74+
- 'v*' # Triggers whenever you push a tag starting with 'v' (e.g., v0.0.2)
75+
76+
jobs:
77+
build-and-publish:
78+
name: Build and publish Python distribution
79+
runs-on: ubuntu-latest
80+
permissions:
81+
# This permission is REQUIRED for Trusted Publishing
82+
id-token: write
83+
contents: read
84+
85+
steps:
86+
- uses: actions/checkout@v4
87+
88+
- name: Set up Python
89+
uses: actions/setup-python@v5
90+
with:
91+
python-version: "3.12"
92+
93+
- name: Install dependencies
94+
run: |
95+
python -m pip install --upgrade pip
96+
pip install build
97+
98+
- name: Build binary wheel and source tarball
99+
run: python -m build
100+
101+
- name: Publish to PyPI
102+
uses: pypa/gh-action-pypi-publish@release/v1
103+
>>>>>>> 8e30c8a94f451d004fdfc990f5ddf8019266eb2f

.github/workflows/release.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # Trigger only on version tags (e.g., v1.0.0)
7+
workflow_dispatch: # allows manual triggering of the workflow from the GitHub Actions tab
8+
9+
jobs:
10+
# 1. TEST JOB: Runs Pytest
11+
test:
12+
uses: ./.github/workflows/test.yml # Reuse the test workflow defined in test.yml
13+
14+
# 2. BUILD: Only runs if 'test' passes
15+
build:
16+
needs: test
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
with:
21+
fetch-depth: 0 # Required for versioning tools to see tags
22+
23+
- name: Set up Python
24+
uses: actions/setup-python@v5
25+
with:
26+
python-version: '3.8.12' # to match pyproject.toml exactly
27+
28+
- name: Build
29+
run: |
30+
pip install build
31+
python -m build .
32+
33+
- name: Upload build artifacts
34+
uses: actions/upload-artifact@v4
35+
with:
36+
name: dist
37+
path: dist/
38+
39+
# 3. GITHUB RELEASE: Creates the release on GitHub and attaches the build files
40+
github-release:
41+
needs: build
42+
runs-on: ubuntu-latest
43+
permissions:
44+
contents: write # Needed to create releases and upload assets
45+
steps:
46+
- name: Download build artifacts
47+
uses: actions/download-artifact@v4
48+
with:
49+
name: dist
50+
path: dist/
51+
52+
- name: Create GitHub Release
53+
uses: softprops/action-gh-release@v2
54+
with:
55+
files: dist/*
56+
generate_release_notes: true # Automatically generate release notes based on commits since the last release
57+
draft: false # Set to true if you want to create a draft release instead of publishing immediately
58+
prerelease: false # Set to true if this is a pre-release (e.g., alpha, beta)
59+
60+
# 4. PUBLISH: Only runs if 'build' passes
61+
publish:
62+
needs: [build, github-release] # Ensure both build and GitHub release steps succeed before publishing
63+
runs-on: ubuntu-latest
64+
# Optional: Use environment protection rule for manual approval before publishing
65+
environment: pypi
66+
permissions:
67+
id-token: write # Needed for authentication with PyPI using GitHub Actions
68+
steps:
69+
- name: Download build artifacts
70+
uses: actions/download-artifact@v4
71+
with:
72+
name: dist
73+
path: dist/
74+
75+
- name: Publish to PyPI
76+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/test.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# This workflow will not run without Autoscript.
2+
name: Test
3+
4+
on:
5+
push:
6+
branches:
7+
- '**' # Trigger on any branch push
8+
pull_request:
9+
branches:
10+
- '**' # Trigger on any pull request
11+
workflow_call: # CRITICAL: Allows this workflow to be called by others
12+
13+
jobs:
14+
test:
15+
name: Run Subset of Tests
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout code
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.8.12'
25+
26+
- name: Install dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install -e ".[dev]"
30+
31+
- name: Run Pytest
32+
run: pytest tests/test_example.py

CITATION.cff

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# This CITATION.cff file was generated with cffinit.
2+
# Visit https://bit.ly/cffinit to generate yours today!
3+
4+
cff-version: 1.2.0
5+
title: pyTriBeam
6+
message: >-
7+
If you use this software, please cite it using these
8+
metadata.
9+
type: software
10+
authors:
11+
- given-names: Andrew
12+
family-names: Polonsky
13+
email: apolon@sandia.gov
14+
affiliation: Sandia National Laboratories
15+
orcid: 'https://orcid.org/0000-0003-4515-9827'
16+
- given-names: James
17+
family-names: Lamb
18+
email: jdlamb@sandia.gov
19+
affiliation: Sandia National Laboratories
20+
orcid: 'https://orcid.org/0000-0002-1409-9799'
21+
- given-names: Chad
22+
family-names: Hovey
23+
affiliation: Sandia National Laboratories
24+
email: chovey@sandia.gov
25+
orcid: 'https://orcid.org/0000-0003-0915-5765'
26+
identifiers:
27+
- type: doi
28+
value: 10.1007/s40192-026-00449-2
29+
description: Paper on software development and use
30+
repository-code: 'https://github.com/sandialabs/pytribeam'
31+
url: 'https://sandialabs.github.io/pytribeam/'
32+
abstract: Automated data collection for the TriBeam microscope
33+
keywords:
34+
- 3D materials science
35+
- serial sectioning
36+
- tomography
37+
- automation
38+
license: MIT

CONTRIBUTING.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Contributing
2+
3+
## Repository Download
4+
5+
```sh
6+
git clone git@github.com:sandialabs/pytribeam.git
7+
```
8+
9+
## Virtual Environment
10+
11+
From within the `pytribeam` directory, create a virtual environment. A virtual environment is a self-contained directory that contains a specific Python installation, along with additional packages. It allows users to create isolated environments for different projects. This ensures that dependencies and libraries do not interfere with each other.
12+
13+
Create a virtual environment with either `pip` or `uv`. `pip` is already included with Python. `uv` must be [installed](https://docs.astral.sh/uv/getting-started/installation/). `uv` is 10 to 100 times faster than `pip`.
14+
15+
```sh
16+
cd pytribeam
17+
18+
# (a) pip method, or
19+
python -m venv .venv
20+
21+
# (b) uv method
22+
uv venv
23+
24+
# for both methods (a) and (b)
25+
source .venv/bin/activate # bash
26+
source .venv/bin/activate.fish # fish shell
27+
```
28+
29+
Install the code in editable form,
30+
31+
```sh
32+
# (a) pip method, or
33+
pip install -e .[dev]
34+
35+
# (b) uv method
36+
uv pip install -e .[dev]
37+
```
38+
39+
## CI/CD
40+
41+
We separate the concerns of test, build, release, and publish throughout the `.github/workflows/` files:
42+
43+
* [`test.yml`](/.github/workflows/test.yml)
44+
* [`release.yml`](/.github/workflows/release.yml)
45+
46+
These YAML files cover:
47+
48+
* **Test (Verification)**
49+
* **Purpose:** To ensure that the code is functional and hasn't introduced regressions (broken existing features).
50+
* **What happens:** Automated tools like `pytest` run your unit and integration tests. It often includes "linting" (checking code style) and type-checking.
51+
* **Key Outcome:** Confidence. If this stage fails, the process stops immediately, preventing broken code from ever reaching a user.
52+
* **Build (Packaging)**
53+
* **Purpose:** To transform your "human-readable" source code into "machine-installable" artifacts.
54+
* **What happens:** Tools (like `python -m build`) bundle your code into standard formats, such as a Wheel (`.whl`) or a Source Distribution (`.tar.gz`).
55+
* **Key Outcome:** Portability. You now have a single file (an "artifact") that contains everything needed to install your library on any compatible system.
56+
* **Release (Documentation & Tagging)**
57+
* **Purpose:** To create an official "point-in-time" snapshot of the project for project management and users.
58+
* **What happens:** A permanent Git tag (like v1.0.0) is assigned to a specific commit. A GitHub Release page is generated with a Changelog (i.e., What's New?) and the build artifacts are attached to it as "Release Assets."
59+
* **Key Outcome:** Traceability. It provides a clear history of the project's evolution and a stable place for users to download specific versions.
60+
* **Publish (Distribution)**
61+
* **Purpose:** To make the software easily available to the global ecosystem.
62+
* **What happens:** The built artifacts are uploaded to a package registry, such as PyPI (the Python Package Index).
63+
* **Key Outcome:** Accessibility. Once published, anyone in the world can install your software using a simple command like `pip install pytribeam`.
64+
65+
Implementation details:
66+
67+
* The reuse of `test.yml` via a `workflow_call` ensures that test logic is not duplicated.
68+
* **Dependency Chain:** `build` waits for `test`, and publish waits for both `build` and `github-release`.
69+
* **Artifact Integrity:** By building once and downing the artifacts in subsequent jobs, we ensure the exact same files go to GitHub and PyPI.
70+
* **Security:** We use `id-token: write` for PyPI's Trusted Publishing, which is a modern and secure way to handle authentication.
71+
72+
In `release.yml` we have removed the manual `-p ${{ secrets.PYPI_TOKEN }}`. The industry standard is now [**Trusted Publishing**](https://docs.pypi.org/trusted-publishers/). You configure this in your PyPI project settings once, and GitHub Actions authenticates securely without you needing to store and rotate secrets.
73+
74+
To configure Trusted Publishing, you tell PyPI, "Trust any code from this specific GitHub repository and workflow." This removes the need to mange long-lived API tokens or passwords in your secrets.
75+
76+
Step:
77+
78+
* Log into your [PyPI](https://pypi.org) account
79+
* Go your project's **Manage** page (or your accounts **Publishing** settings if you are setting it up for the first time.)
80+
* Look for the **Publishing**tab
81+
* Click **Add new publisher**
82+
* Select **GitHub** as the source
83+
* Enter the following details:
84+
* Owner: sandialabs
85+
* Repository name: pytribeam
86+
* Workflow name: `release.yml` (This must match your filename in your `.github/workflows/` directory))
87+
* Environment name: You can leave this blank or name it `pypi` (if you use it in your YAML). We used `pypi`.
88+
* Click the **Add** button
89+
90+
To create a release:
91+
92+
* Merge the `dev` branch into the `main` branch.
93+
* On the `main` branch, `git tag` and push to `main`, e.g.,
94+
95+
```sh
96+
# Ensure you are on the main branch
97+
git checkout main
98+
git pull
99+
100+
# View existing tags, if any
101+
git tag
102+
103+
# Create the new tag, e.g.,
104+
git tag -a v1.0.0 -m "Release version 1.0.0"
105+
106+
# On the main branch, push the tag to GitHub
107+
git push origin v1.0.0
108+
```

0 commit comments

Comments
 (0)