Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a93edf16a1 | ||
|
|
69de6b7bde | ||
|
|
29ec2fe7ab | ||
|
|
99e54a2e52 | ||
|
|
4c65582ada | ||
|
|
3cd251636e | ||
|
|
fb3679fcf8 | ||
|
|
916dc0d645 | ||
|
|
4c39d6f8ee | ||
|
|
19a38d9df6 | ||
|
|
8cff9d9141 | ||
|
|
e83d603047 | ||
|
|
cb1c1d985c | ||
|
|
71bab40e53 | ||
|
|
667fdde139 | ||
|
|
d42d283def | ||
|
|
bad162bdce | ||
|
|
5812860910 | ||
|
|
1a313c8e16 | ||
|
|
785502ea9e | ||
|
|
c20ae68d07 | ||
|
|
ca9195daca | ||
|
|
aa93ced550 | ||
|
|
3a6264a608 | ||
|
|
8af0f02a5a | ||
|
|
3c0211285a | ||
|
|
4aac193439 | ||
|
|
c195a11759 | ||
|
|
31acb9e844 | ||
|
|
ff31170fd6 | ||
|
|
4634c135e7 | ||
|
|
c1e6a31120 | ||
|
|
62cc66f9e5 | ||
|
|
a40397fabc | ||
|
|
acbc4c3074 | ||
|
|
fa777c6a79 | ||
|
|
c58a55220f | ||
|
|
68c1f878a2 | ||
|
|
25f72f2ac4 | ||
|
|
f4cdfc01aa | ||
|
|
13aeb5001b | ||
|
|
74a93aaa7c | ||
|
|
9c08afa728 | ||
|
|
32937d1ca7 | ||
|
|
cee841830c | ||
|
|
ca004e5206 | ||
|
|
3689c955f9 | ||
|
|
fbf93e679f | ||
|
|
3c4cfaa23c | ||
|
|
ffde3ed1dd | ||
|
|
ffd6c56f44 |
No files matched your search
@@ -1,8 +0,0 @@
|
|||||||
[alias]
|
|
||||||
xtask = "run --package xtask --"
|
|
||||||
|
|
||||||
# Windows release binaries link the C runtime statically, so they run without the VC++
|
|
||||||
# redistributable (packaging/windows/package.ps1 builds with --target, which keeps the flag
|
|
||||||
# off build scripts and proc-macros).
|
|
||||||
[target.x86_64-pc-windows-msvc]
|
|
||||||
rustflags = ["-C", "target-feature=+crt-static"]
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Every change to FieldCraft needs the maintainer's review before it merges.
|
|
||||||
* @jyviko
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
name: Bug report
|
|
||||||
description: Something FieldCraft does wrong, a wrong result, or a crash
|
|
||||||
labels: [bug]
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: observed
|
|
||||||
attributes:
|
|
||||||
label: Observed failure
|
|
||||||
description: Exactly what happened. Quote error messages and wrong numbers as they appear.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: reproduction
|
|
||||||
attributes:
|
|
||||||
label: Reproduction
|
|
||||||
description: Numbered steps, or a script (`fieldcraft-cli run script.json`, control-channel JSON lines), with the sample, corpus part or attached `.fieldcraft` / `.solidcraft` file that shows it.
|
|
||||||
placeholder: |
|
|
||||||
1. fieldcraft --sample cantilever
|
|
||||||
2. Mesh ▸ Tet ▸ OK
|
|
||||||
3. ...
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: evidence
|
|
||||||
attributes:
|
|
||||||
label: Evidence
|
|
||||||
description: Screenshots, log output, numbers. For a crash, attach the crash report (`fieldcraft-cli crashes`, then `crashes show <id>`).
|
|
||||||
- type: textarea
|
|
||||||
id: expected
|
|
||||||
attributes:
|
|
||||||
label: Expected behaviour
|
|
||||||
description: What should happen instead, and why — a closed form, a published benchmark, the documentation, or how the rest of the app behaves. Never output from a commercial CAE product.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: investigation
|
|
||||||
attributes:
|
|
||||||
label: Investigation
|
|
||||||
description: Anything you found about the cause — code you suspect, what you ruled out. Leave empty if you have not looked.
|
|
||||||
- type: input
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version and platform
|
|
||||||
placeholder: "v0.5.5 (or commit), macOS 15 arm64"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
name: Feature request
|
|
||||||
description: A capability FieldCraft should have
|
|
||||||
labels: [enhancement]
|
|
||||||
body:
|
|
||||||
- type: textarea
|
|
||||||
id: current
|
|
||||||
attributes:
|
|
||||||
label: Current behaviour
|
|
||||||
description: What you can and cannot do today, and what happens when you try.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: need
|
|
||||||
attributes:
|
|
||||||
label: What you need and why
|
|
||||||
description: The analysis or workflow you are trying to do.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: expected
|
|
||||||
attributes:
|
|
||||||
label: Expected behaviour
|
|
||||||
description: What FieldCraft should do, as precisely as you can.
|
|
||||||
- type: textarea
|
|
||||||
id: reference
|
|
||||||
attributes:
|
|
||||||
label: References
|
|
||||||
description: Papers, textbooks, public specifications or published benchmarks that define the behaviour. Do not paste text, files or results from commercial CAE products.
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
# Weekly dependency updates against develop, the trunk, grouped so each ecosystem opens one pull
|
|
||||||
# request a week. Security updates are switched on in the repository settings and open their own
|
|
||||||
# pull requests as advisories appear. CI runs the full gate on Dependabot's pull requests
|
|
||||||
# (.github/workflows/ci.yml).
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: cargo
|
|
||||||
directory: /
|
|
||||||
target-branch: develop
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
day: monday
|
|
||||||
time: "05:00"
|
|
||||||
timezone: Etc/UTC
|
|
||||||
open-pull-requests-limit: 5
|
|
||||||
commit-message:
|
|
||||||
prefix: deps
|
|
||||||
groups:
|
|
||||||
# Compatible updates (Cargo.lock only) in one pull request; a breaking release of a
|
|
||||||
# dependency comes on its own, since it usually needs code changes.
|
|
||||||
cargo-compatible:
|
|
||||||
update-types: [minor, patch]
|
|
||||||
ignore:
|
|
||||||
# Pinned to the SolidCraft commit FieldCraft builds against, together with the truck and
|
|
||||||
# egui-wgpu patches from that commit ([patch.crates-io] in Cargo.toml); moved by hand.
|
|
||||||
- dependency-name: "solidcraft-*"
|
|
||||||
- dependency-name: "truck-*"
|
|
||||||
- dependency-name: matext4cgmath
|
|
||||||
- dependency-name: egui-wgpu
|
|
||||||
# The egui line follows SolidCraft's (its egui-wgpu fixes are patched in): patch releases
|
|
||||||
# come with the group, a new line (0.36 -> 0.37) moves by hand with SolidCraft.
|
|
||||||
- dependency-name: egui
|
|
||||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
||||||
- dependency-name: eframe
|
|
||||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
||||||
# The shared Craft components follow VectorCraft's rev.
|
|
||||||
- dependency-name: craft-ui
|
|
||||||
# The exact predicates' BigInt must be num-rational's (0.4 uses num-bigint 0.4): both move
|
|
||||||
# together, by hand.
|
|
||||||
- dependency-name: num-bigint
|
|
||||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
||||||
- dependency-name: num-rational
|
|
||||||
update-types: ["version-update:semver-major", "version-update:semver-minor"]
|
|
||||||
|
|
||||||
- package-ecosystem: github-actions
|
|
||||||
directory: /
|
|
||||||
target-branch: develop
|
|
||||||
schedule:
|
|
||||||
interval: weekly
|
|
||||||
day: monday
|
|
||||||
time: "05:00"
|
|
||||||
timezone: Etc/UTC
|
|
||||||
open-pull-requests-limit: 3
|
|
||||||
commit-message:
|
|
||||||
prefix: ci
|
|
||||||
groups:
|
|
||||||
# Actions are pinned by commit SHA with a version comment; Dependabot updates both.
|
|
||||||
actions:
|
|
||||||
patterns: ["*"]
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
Closes #
|
|
||||||
|
|
||||||
## What and why
|
|
||||||
|
|
||||||
## How it was verified
|
|
||||||
<!-- Tests added or changed; oracle cases (tests/oracle) for solver and meshing results, with their cited references. -->
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
- [ ] The issue was assigned to me before I started (see CONTRIBUTING.md)
|
|
||||||
- [ ] `cargo fmt --all`, `cargo clippy -p <crates I touched> --all-targets -- -D warnings` and their tests pass
|
|
||||||
- [ ] No code, text or data from GPL-family projects or commercial CAE products
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
FieldCraft is open-source CAE pre-processing in Rust: it turns geometry into analysis-ready
|
|
||||||
finite element models, writes Abaqus, Nastran and LS-DYNA decks, and solves linear static and
|
|
||||||
modal problems with its own solver. AI agents can drive it over MCP (`fieldcraft-cli mcp`).
|
|
||||||
[README](https://github.com/jyviko/fieldcraft#readme) ·
|
|
||||||
[roadmap](https://github.com/jyviko/fieldcraft/blob/main/ROADMAP.md) ·
|
|
||||||
[issues](https://github.com/jyviko/fieldcraft/issues)
|
|
||||||
|
|
||||||
**Which file?**
|
|
||||||
- **macOS 11+** (Apple silicon and Intel): open `fieldcraft-{version}-macos-universal.dmg` and
|
|
||||||
drag `FieldCraft.app` onto Applications. The command-line tool is in
|
|
||||||
`fieldcraft-cli-{version}-macos-universal.zip`.
|
|
||||||
- **Linux** (x86_64, glibc 2.35+: Ubuntu 22.04, Debian 12, Fedora 36 or newer):
|
|
||||||
`fieldcraft-{version}-linux-x86_64.AppImage` (`chmod +x`, then run it), or unpack
|
|
||||||
`fieldcraft-{version}-linux-x86_64.tar.gz` and run `bin/fieldcraft` (`bin/fieldcraft-cli` is the
|
|
||||||
command-line tool).
|
|
||||||
- **Windows 10+** (x64): unzip `fieldcraft-{version}-windows-x64.zip` and run `fieldcraft.exe`
|
|
||||||
(`fieldcraft-cli.exe` is the command-line tool).
|
|
||||||
- `SHA256SUMS.txt`: `sha256sum -c SHA256SUMS.txt --ignore-missing` (macOS:
|
|
||||||
`shasum -a 256 -c SHA256SUMS.txt --ignore-missing`).
|
|
||||||
|
|
||||||
To start with a sample model, run the app with `--sample cantilever` (macOS:
|
|
||||||
`/Applications/FieldCraft.app/Contents/MacOS/FieldCraft --sample cantilever`).
|
|
||||||
|
|
||||||
**Signing.** {macos_signing} The Linux and Windows builds are not signed; on Windows, SmartScreen
|
|
||||||
may say "Windows protected your PC": choose **More info**, then **Run anyway**.
|
|
||||||
|
|
||||||
Every package carries `LICENSE-MIT`, `LICENSE-APACHE`, `NOTICE` and `THIRD-PARTY-LICENSES.txt`.
|
|
||||||
@@ -1,83 +0,0 @@
|
|||||||
# Linux on other architectures, weekly and on demand: CI and the release build x86_64 Linux,
|
|
||||||
# macOS and Windows only.
|
|
||||||
# - arm64: a native runner builds the shipped binaries (release profile) and runs the CLI and
|
|
||||||
# engine tests.
|
|
||||||
# - riscv64: cross-built with Ubuntu's GNU toolchain and linked; the CLI then runs under QEMU.
|
|
||||||
# The GUI needs no target system libraries at link time (Wayland, X11 and GL are opened at run
|
|
||||||
# time), so only the cross C toolchain and libc are installed.
|
|
||||||
# The RISC-V job is adapted from SolidCraft's CI (see ATTRIBUTION.md).
|
|
||||||
name: Linux arm64 and riscv64
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '17 5 * * 1'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: arch-check-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
arm64:
|
|
||||||
name: Linux arm64 (native)
|
|
||||||
runs-on: ubuntu-24.04-arm
|
|
||||||
timeout-minutes: 90
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: arm64
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
- name: Build fieldcraft and fieldcraft-cli (release)
|
|
||||||
run: cargo build --locked --release -p fieldcraft -p fieldcraft-cli
|
|
||||||
- name: Run the binaries
|
|
||||||
run: |
|
|
||||||
file target/release/fieldcraft target/release/fieldcraft-cli
|
|
||||||
target/release/fieldcraft --version
|
|
||||||
target/release/fieldcraft-cli --version
|
|
||||||
target/release/fieldcraft-cli commands >/dev/null
|
|
||||||
- name: CLI and engine tests
|
|
||||||
run: cargo test --locked --profile ci -p fieldcraft-cli -p fieldcraft-engine
|
|
||||||
|
|
||||||
riscv64:
|
|
||||||
name: Linux riscv64 (cross)
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
TARGET: riscv64gc-unknown-linux-gnu
|
|
||||||
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER: riscv64-linux-gnu-gcc
|
|
||||||
CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_RUNNER: qemu-riscv64 -L /usr/riscv64-linux-gnu
|
|
||||||
CC_riscv64gc_unknown_linux_gnu: riscv64-linux-gnu-gcc
|
|
||||||
CXX_riscv64gc_unknown_linux_gnu: riscv64-linux-gnu-g++
|
|
||||||
AR_riscv64gc_unknown_linux_gnu: riscv64-linux-gnu-ar
|
|
||||||
PKG_CONFIG_ALLOW_CROSS: 1
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: riscv64gc-unknown-linux-gnu
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: riscv64
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
- name: Install the cross toolchain and QEMU
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y --no-install-recommends gcc-riscv64-linux-gnu g++-riscv64-linux-gnu \
|
|
||||||
libc6-dev-riscv64-cross qemu-user
|
|
||||||
- name: Build fieldcraft and fieldcraft-cli
|
|
||||||
run: cargo build --locked --profile ci --target "$TARGET" -p fieldcraft -p fieldcraft-cli
|
|
||||||
- name: Run the CLI under QEMU
|
|
||||||
run: |
|
|
||||||
bin="target/$TARGET/ci"
|
|
||||||
file "$bin/fieldcraft" "$bin/fieldcraft-cli"
|
|
||||||
qemu-riscv64 -L /usr/riscv64-linux-gnu "$bin/fieldcraft-cli" --version
|
|
||||||
qemu-riscv64 -L /usr/riscv64-linux-gnu "$bin/fieldcraft-cli" commands >/dev/null
|
|
||||||
qemu-riscv64 -L /usr/riscv64-linux-gnu "$bin/fieldcraft" --version
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
name: CI
|
|
||||||
|
|
||||||
# CI runs once per merge on `develop`, the trunk (AGENTS.md, "Workflow for every change"): the core
|
|
||||||
# team's pull requests are checked locally on the crates they touch and merged; a red trunk is
|
|
||||||
# fixed forward. `main` holds released code only (docs/releasing.md).
|
|
||||||
# Pull requests from forks (outside contributors) run the full gate, once the maintainer approves
|
|
||||||
# the run, so the review sees it; so do Dependabot's (.github/dependabot.yml), which nobody tests
|
|
||||||
# locally. The heavy job stays off pull requests.
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- '**'
|
|
||||||
- '!**/*.md'
|
|
||||||
- '!docs/**'
|
|
||||||
- 'docs/features.md'
|
|
||||||
- 'docs/oracle.md'
|
|
||||||
push:
|
|
||||||
branches: [develop]
|
|
||||||
# A merge that only touches prose starts no run. The generated pages are checked by the jobs
|
|
||||||
# (features.md by `cargo xtask ci`, oracle.md by the oracle job), so they still count.
|
|
||||||
# (Later patterns override earlier ones.)
|
|
||||||
paths:
|
|
||||||
- '**'
|
|
||||||
- '!**/*.md'
|
|
||||||
- '!docs/**'
|
|
||||||
- 'docs/features.md'
|
|
||||||
- 'docs/oracle.md'
|
|
||||||
schedule:
|
|
||||||
# Nightly, on the default branch (develop): the heavy tests.
|
|
||||||
- cron: '23 3 * * *'
|
|
||||||
# Weekly: the oracle on macOS too, so results that differ by platform show up in CI (the
|
|
||||||
# fixtures are often blessed on a Mac; #115).
|
|
||||||
- cron: '41 4 * * 0'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
# A newer merge cancels the run still going for the one before it, so a burst of merges is tested
|
|
||||||
# once, at the tip. Nightly and manual runs are grouped apart and never cancelled by a merge.
|
|
||||||
concurrency:
|
|
||||||
group: ci-${{ github.ref }}-${{ github.event_name }}
|
|
||||||
cancel-in-progress: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ci:
|
|
||||||
name: cargo xtask ci
|
|
||||||
if: github.event.schedule != '41 4 * * 0' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository || github.event.pull_request.user.login == 'dependabot[bot]')
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 60
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
components: rustfmt, clippy
|
|
||||||
targets: wasm32-unknown-unknown
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
# A dependency update changes THIRD-PARTY-LICENSES.txt, which Dependabot cannot regenerate:
|
|
||||||
# regenerate it here so the gate checks everything else, and dependabot-licences.yml commits
|
|
||||||
# it to the pull request.
|
|
||||||
- name: Regenerate THIRD-PARTY-LICENSES.txt (Dependabot)
|
|
||||||
if: github.event.pull_request.user.login == 'dependabot[bot]'
|
|
||||||
run: cargo xtask licences
|
|
||||||
- run: cargo xtask ci
|
|
||||||
|
|
||||||
heavy:
|
|
||||||
# The heavy verification and corpus tests (#[ignore]d) and the doc tests.
|
|
||||||
name: cargo xtask test --heavy
|
|
||||||
if: github.event.schedule != '41 4 * * 0' && github.event_name != 'pull_request'
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 60
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
- run: cargo xtask test --heavy
|
|
||||||
|
|
||||||
oracle:
|
|
||||||
# Verification and validation (docs/verification.md): every case against its reference and
|
|
||||||
# its fixture, and docs/oracle.md must be the table the cases produce. Cases marked `slow`
|
|
||||||
# run here too while the whole set stays within a few minutes; `--quick` skips them.
|
|
||||||
name: cargo xtask oracle
|
|
||||||
if: github.event.schedule != '41 4 * * 0' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository || github.event.pull_request.user.login == 'dependabot[bot]')
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 45
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: oracle
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
- run: cargo xtask oracle
|
|
||||||
- name: docs/oracle.md is current
|
|
||||||
run: git diff --exit-code docs/oracle.md
|
|
||||||
|
|
||||||
oracle-macos:
|
|
||||||
# The same oracle on macOS, weekly and on demand: the solvers must agree across platforms
|
|
||||||
# to the fixture bands, and docs/oracle.md must read the same.
|
|
||||||
name: cargo xtask oracle (macOS)
|
|
||||||
if: github.event.schedule == '41 4 * * 0' || github.event_name == 'workflow_dispatch'
|
|
||||||
runs-on: macos-14
|
|
||||||
timeout-minutes: 60
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: oracle-macos
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
- run: cargo xtask oracle
|
|
||||||
- name: docs/oracle.md is current
|
|
||||||
run: git diff --exit-code docs/oracle.md
|
|
||||||
|
|
||||||
advisories:
|
|
||||||
name: Dependency advisories and sources
|
|
||||||
if: github.event.schedule != '41 4 * * 0' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.repository || github.event.pull_request.user.login == 'dependabot[bot]')
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 20
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- name: Install cargo-deny
|
|
||||||
run: cargo install cargo-deny --version 0.20.2 --locked
|
|
||||||
- run: cargo deny --locked check --warn unmaintained advisories bans sources
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
# Dependabot's Cargo updates change THIRD-PARTY-LICENSES.txt (`cargo xtask licences`), which
|
|
||||||
# Dependabot cannot regenerate: this commits the regenerated file to its pull request. CI's own
|
|
||||||
# run on the pull request regenerates it too, so its result covers everything else.
|
|
||||||
name: Dependabot licences
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches: [develop]
|
|
||||||
paths: [Cargo.lock]
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: dependabot-licences-${{ github.head_ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
licences:
|
|
||||||
if: github.event.pull_request.user.login == 'dependabot[bot]'
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 20
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
with:
|
|
||||||
ref: ${{ github.head_ref }}
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- run: cargo xtask licences
|
|
||||||
- name: Commit the regenerated file
|
|
||||||
run: |
|
|
||||||
if git diff --quiet -- THIRD-PARTY-LICENSES.txt; then
|
|
||||||
echo "THIRD-PARTY-LICENSES.txt is up to date"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
# [skip ci]: the pull request's CI run already regenerated this file and tested the
|
|
||||||
# tree with it; a bot-authored commit would otherwise wait for a maintainer's approval.
|
|
||||||
git commit -m "deps: regenerate THIRD-PARTY-LICENSES.txt [skip ci]" -- THIRD-PARTY-LICENSES.txt
|
|
||||||
git push origin "HEAD:${GITHUB_HEAD_REF}"
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
# Quick static checks for the release pipeline (seconds, no Rust build): workflow syntax, the
|
|
||||||
# packaging shell and PowerShell scripts, the macOS property lists and the Linux desktop entry.
|
|
||||||
# These files are otherwise exercised only by a full release run (release.yml).
|
|
||||||
# Adapted from SolidCraft's packaging-lint.yml, itself adapted from PhotoCraft's (see ATTRIBUTION.md).
|
|
||||||
name: Packaging lint
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [develop]
|
|
||||||
paths: [".github/workflows/**", "packaging/**"]
|
|
||||||
pull_request:
|
|
||||||
paths: [".github/workflows/**", "packaging/**"]
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: packaging-lint-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lint:
|
|
||||||
name: Packaging lint
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 10
|
|
||||||
env:
|
|
||||||
ACTIONLINT_VERSION: 1.7.12
|
|
||||||
ACTIONLINT_SHA256: 8aca8db96f1b94770f1b0d72b6dddcb1ebb8123cb3712530b08cc387b349a3d8
|
|
||||||
PSSCRIPTANALYZER_VERSION: 1.24.0
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- name: Install tools
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y --no-install-recommends shellcheck desktop-file-utils libxml2-utils
|
|
||||||
archive="$RUNNER_TEMP/actionlint.tar.gz"
|
|
||||||
curl -fsSL -o "$archive" \
|
|
||||||
"https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz"
|
|
||||||
echo "$ACTIONLINT_SHA256 $archive" | sha256sum -c -
|
|
||||||
tar -xzf "$archive" -C "$RUNNER_TEMP" actionlint
|
|
||||||
- name: actionlint
|
|
||||||
# Also runs shellcheck on every `run:` script.
|
|
||||||
run: '"$RUNNER_TEMP/actionlint" -color'
|
|
||||||
- name: shellcheck
|
|
||||||
# packaging/.shellcheckrc lets the scripts' `source=../env.sh` directives resolve.
|
|
||||||
run: shellcheck packaging/*.sh packaging/*/*.sh packaging/linux/AppRun
|
|
||||||
- name: PowerShell
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
$failed = $false
|
|
||||||
foreach ($f in Get-ChildItem packaging/windows/*.ps1) {
|
|
||||||
$errors = $null
|
|
||||||
[System.Management.Automation.Language.Parser]::ParseFile($f.FullName, [ref]$null, [ref]$errors) | Out-Null
|
|
||||||
if ($errors) {
|
|
||||||
$errors | ForEach-Object { Write-Output "::error file=$($f.FullName),line=$($_.Extent.StartLineNumber)::$($_.Message)" }
|
|
||||||
$failed = $true
|
|
||||||
} else {
|
|
||||||
Write-Output "parsed $($f.Name)"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($failed) { exit 1 }
|
|
||||||
if (-not (Get-Module -ListAvailable PSScriptAnalyzer | Where-Object Version -eq $env:PSSCRIPTANALYZER_VERSION)) {
|
|
||||||
Install-Module PSScriptAnalyzer -RequiredVersion $env:PSSCRIPTANALYZER_VERSION -Scope CurrentUser -Force
|
|
||||||
}
|
|
||||||
Import-Module PSScriptAnalyzer -RequiredVersion $env:PSSCRIPTANALYZER_VERSION
|
|
||||||
$issues = Invoke-ScriptAnalyzer -Path packaging/windows -Recurse -Severity Error, Warning
|
|
||||||
$issues | ForEach-Object { Write-Output "::error file=$($_.ScriptPath),line=$($_.Line)::$($_.RuleName): $($_.Message)" }
|
|
||||||
if ($issues) { exit 1 }
|
|
||||||
- name: Property lists and desktop entry
|
|
||||||
run: |
|
|
||||||
app_id="$(sed -n 's/^APP_ID=//p' packaging/env.sh)"
|
|
||||||
test -n "$app_id"
|
|
||||||
xmllint --noout packaging/macos/*.plist*
|
|
||||||
desktop="packaging/linux/$app_id.desktop"
|
|
||||||
desktop-file-validate "$desktop"
|
|
||||||
# The window's X11 class / Wayland app_id is packaging's APP_ID (apps/fieldcraft/src/main.rs).
|
|
||||||
grep -qx "StartupWMClass=$app_id" "$desktop"
|
|
||||||
grep -qF "const APP_ID: &str = \"$app_id\";" apps/fieldcraft/src/main.rs
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
# The web app (apps/fieldcraft-web, docs/web.md) on GitHub Pages: https://jyviko.github.io/fieldcraft/
|
|
||||||
# After SolidCraft's pages.yml (MIT OR Apache-2.0; see ATTRIBUTION.md).
|
|
||||||
#
|
|
||||||
# A push to `main` (a release; main holds released code only) builds the app with Trunk (release,
|
|
||||||
# wasm-opt) and deploys it. A merge to `develop` that touches code builds it without deploying, so a
|
|
||||||
# broken web build shows up before the release. A manual run builds the branch it runs on and
|
|
||||||
# deploys only from `main`. Needs Settings › Pages › Source = GitHub Actions, and `main` allowed
|
|
||||||
# by the github-pages environment's deployment branches.
|
|
||||||
name: Pages
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main, develop]
|
|
||||||
# As ci.yml: a merge that only touches prose builds nothing.
|
|
||||||
paths:
|
|
||||||
- '**'
|
|
||||||
- '!**/*.md'
|
|
||||||
- '!docs/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
# One deployment at a time; a newer push waits its turn instead of cancelling a deploy part way.
|
|
||||||
concurrency:
|
|
||||||
group: pages-${{ github.ref }}
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
TRUNK_VERSION: v0.21.14
|
|
||||||
TRUNK_SHA256: f2b4680cd239693a646a2795e4633c625328d7b2a044fbe749fa3a2fe9e7036b
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
timeout-minutes: 60
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: wasm32-unknown-unknown
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: web
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/develop' }}
|
|
||||||
- name: Install Trunk
|
|
||||||
run: |
|
|
||||||
mkdir -p "$HOME/.local/bin"
|
|
||||||
curl -sSfL -o trunk.tar.gz "https://github.com/trunk-rs/trunk/releases/download/${TRUNK_VERSION}/trunk-x86_64-unknown-linux-gnu.tar.gz"
|
|
||||||
echo "${TRUNK_SHA256} trunk.tar.gz" | sha256sum -c -
|
|
||||||
tar -xzf trunk.tar.gz -C "$HOME/.local/bin"
|
|
||||||
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
|
|
||||||
- name: Build the web app
|
|
||||||
working-directory: apps/fieldcraft-web
|
|
||||||
run: trunk build --release --public-url /fieldcraft/
|
|
||||||
- name: Bundle size
|
|
||||||
run: |
|
|
||||||
{
|
|
||||||
echo "### Web app bundle"
|
|
||||||
echo '| file | bytes | gzip |'
|
|
||||||
echo '|---|---:|---:|'
|
|
||||||
for f in dist/web/*.wasm dist/web/*.js; do
|
|
||||||
echo "| $(basename "$f") | $(stat -c %s "$f") | $(gzip -9 -c "$f" | wc -c) |"
|
|
||||||
done
|
|
||||||
} >> "$GITHUB_STEP_SUMMARY"
|
|
||||||
- if: github.ref == 'refs/heads/main'
|
|
||||||
uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
|
||||||
with:
|
|
||||||
path: dist/web
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
if: github.ref == 'refs/heads/main'
|
|
||||||
needs: build
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
permissions:
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
environment:
|
|
||||||
name: github-pages
|
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
|
||||||
steps:
|
|
||||||
- id: deployment
|
|
||||||
uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
# Release builds (docs/releasing.md), after SolidCraft's and VectorCraft's release.yml
|
|
||||||
# (MIT OR Apache-2.0; see ATTRIBUTION.md).
|
|
||||||
#
|
|
||||||
# A push to `main` (fast-forwarded from a verified `develop` commit; main holds released code only)
|
|
||||||
# builds every package and creates or updates the
|
|
||||||
# DRAFT GitHub Release "FieldCraft v<version>", with SHA256SUMS.txt and generated notes. The
|
|
||||||
# version is [workspace.package] version in Cargo.toml; a suffix (0.2.0-rc.1) makes a
|
|
||||||
# pre-release. A person verifies the draft and publishes it; this workflow never publishes,
|
|
||||||
# and pushes to develop or tags never start it.
|
|
||||||
#
|
|
||||||
# macOS universal (arm64 + x86_64) .dmg with FieldCraft.app, the CLI as a .zip packaging/macos
|
|
||||||
# Linux x86_64 (glibc 2.35+) .tar.gz and .AppImage packaging/linux
|
|
||||||
# Windows x64 .zip with fieldcraft.exe and fieldcraft-cli.exe packaging/windows
|
|
||||||
#
|
|
||||||
# macOS: signed with a Developer ID and notarized when the APPLE_* secrets exist, ad-hoc
|
|
||||||
# otherwise (the release notes say which). Linux and Windows builds are not signed.
|
|
||||||
#
|
|
||||||
# Dry run: `gh workflow run release.yml --ref <branch>` builds everything and uploads the
|
|
||||||
# `release-assets` artifact without creating a release. `-f draft=true` on `main` retries
|
|
||||||
# the draft.
|
|
||||||
name: Release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
draft:
|
|
||||||
description: "Create/update the draft release (main only; off: build artifacts only)"
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: release-${{ github.ref }}
|
|
||||||
# Never cancel a run mid-notarization or mid-upload; a newer push waits its turn.
|
|
||||||
cancel-in-progress: false
|
|
||||||
|
|
||||||
env:
|
|
||||||
CARGO_TERM_COLOR: always
|
|
||||||
CARGO_INCREMENTAL: 0
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
version:
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
outputs:
|
|
||||||
version: ${{ steps.v.outputs.version }}
|
|
||||||
prerelease: ${{ steps.v.outputs.prerelease }}
|
|
||||||
draft: ${{ steps.v.outputs.draft }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- id: v
|
|
||||||
name: Resolve the version
|
|
||||||
env:
|
|
||||||
REQUEST_DRAFT: ${{ github.event_name == 'push' || inputs.draft }}
|
|
||||||
run: |
|
|
||||||
. packaging/env.sh
|
|
||||||
if ! printf '%s' "$VERSION" | grep -Eq '^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$'; then
|
|
||||||
echo "::error::Cargo.toml must contain a version like 1.2.3 or 1.2.3-rc.1, not '$VERSION'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$REQUEST_DRAFT" = true ] && [ "$GITHUB_REF" != refs/heads/main ]; then
|
|
||||||
echo "::error::Draft releases are built from main only"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
case "$VERSION" in *-*) pre=true ;; *) pre=false ;; esac
|
|
||||||
{ echo "version=$VERSION"; echo "prerelease=$pre"; echo "draft=$REQUEST_DRAFT"; } >>"$GITHUB_OUTPUT"
|
|
||||||
echo "### FieldCraft v$VERSION (\`${GITHUB_SHA::9}\`)" >>"$GITHUB_STEP_SUMMARY"
|
|
||||||
|
|
||||||
macos:
|
|
||||||
name: macOS universal
|
|
||||||
needs: version
|
|
||||||
runs-on: macos-14
|
|
||||||
timeout-minutes: 120
|
|
||||||
outputs:
|
|
||||||
signing: ${{ steps.package.outputs.signing }}
|
|
||||||
env:
|
|
||||||
FIELDCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: aarch64-apple-darwin, x86_64-apple-darwin
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: release-macos-universal
|
|
||||||
# Release runs are rare: only release-branch runs keep a cache, so dry runs don't evict CI's.
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
||||||
- name: Import the signing certificate (skipped without APPLE_CERTIFICATE)
|
|
||||||
env:
|
|
||||||
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
|
|
||||||
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
|
|
||||||
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
|
|
||||||
run: packaging/macos/import-cert.sh
|
|
||||||
- name: Build, sign, notarize and package (the dmg is mounted and checked)
|
|
||||||
id: package
|
|
||||||
env:
|
|
||||||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
|
||||||
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
|
|
||||||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
|
||||||
run: packaging/macos/package.sh --arch universal
|
|
||||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
||||||
with:
|
|
||||||
name: release-macos
|
|
||||||
path: dist/release/*
|
|
||||||
if-no-files-found: error
|
|
||||||
- name: Remove the temporary keychain
|
|
||||||
if: always()
|
|
||||||
run: |
|
|
||||||
if [ -n "${MACOS_KEYCHAIN:-}" ]; then security delete-keychain "$MACOS_KEYCHAIN" || true; fi
|
|
||||||
|
|
||||||
linux:
|
|
||||||
name: Linux x86_64
|
|
||||||
needs: version
|
|
||||||
# The oldest GitHub-hosted image, so the binaries need only glibc >= 2.35.
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
FIELDCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- name: Install packaging tools
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y --no-install-recommends desktop-file-utils
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: release-linux-x86_64
|
|
||||||
# Release runs are rare: only release-branch runs keep a cache, so dry runs don't evict CI's.
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
||||||
- name: Build and package (tar.gz, AppImage)
|
|
||||||
run: packaging/linux/package.sh
|
|
||||||
- name: Check the packages
|
|
||||||
run: |
|
|
||||||
. packaging/env.sh
|
|
||||||
list="$(tar -tzf dist/release/*.tar.gz)"
|
|
||||||
for f in bin/fieldcraft bin/fieldcraft-cli "share/applications/$APP_ID.desktop" \
|
|
||||||
share/doc/fieldcraft/THIRD-PARTY-LICENSES.txt; do
|
|
||||||
grep -Fx -- "fieldcraft-$VERSION-linux-x86_64/$f" <<<"$list"
|
|
||||||
done
|
|
||||||
ldd target/release/fieldcraft
|
|
||||||
for appimage in dist/release/*.AppImage; do
|
|
||||||
chmod +x "$appimage"
|
|
||||||
APPIMAGE_EXTRACT_AND_RUN=1 "$appimage" --version
|
|
||||||
done
|
|
||||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
||||||
with:
|
|
||||||
name: release-linux-x86_64
|
|
||||||
path: dist/release/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
windows:
|
|
||||||
name: Windows x64
|
|
||||||
needs: version
|
|
||||||
runs-on: windows-latest
|
|
||||||
timeout-minutes: 90
|
|
||||||
env:
|
|
||||||
FIELDCRAFT_VERSION: ${{ needs.version.outputs.version }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
|
||||||
with:
|
|
||||||
targets: x86_64-pc-windows-msvc
|
|
||||||
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
|
|
||||||
with:
|
|
||||||
key: release-windows-x64
|
|
||||||
# Release runs are rare: only release-branch runs keep a cache, so dry runs don't evict CI's.
|
|
||||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
|
||||||
- name: Build and package (zip)
|
|
||||||
shell: pwsh
|
|
||||||
run: ./packaging/windows/package.ps1
|
|
||||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
||||||
with:
|
|
||||||
name: release-windows-x64
|
|
||||||
path: dist/release/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
release:
|
|
||||||
name: Draft release (or dry-run artifacts)
|
|
||||||
needs: [version, macos, linux, windows]
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
env:
|
|
||||||
VERSION: ${{ needs.version.outputs.version }}
|
|
||||||
PRERELEASE: ${{ needs.version.outputs.prerelease }}
|
|
||||||
MACOS_SIGNING: ${{ needs.macos.outputs.signing }}
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
GH_REPO: ${{ github.repository }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
||||||
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
||||||
with:
|
|
||||||
pattern: release-*
|
|
||||||
path: artifacts
|
|
||||||
merge-multiple: true
|
|
||||||
- name: Check the set, checksums and notes
|
|
||||||
run: |
|
|
||||||
for f in "fieldcraft-$VERSION-macos-universal.dmg" "fieldcraft-cli-$VERSION-macos-universal.zip" \
|
|
||||||
"fieldcraft-$VERSION-linux-x86_64.tar.gz" "fieldcraft-$VERSION-linux-x86_64.AppImage" \
|
|
||||||
"fieldcraft-$VERSION-windows-x64.zip"; do
|
|
||||||
test -s "artifacts/$f" || { echo "::error::missing $f"; exit 1; }
|
|
||||||
done
|
|
||||||
(cd artifacts && sha256sum -- * | tee SHA256SUMS.txt)
|
|
||||||
# The macOS paragraph says how the app was signed (packaging/macos/package.sh).
|
|
||||||
case "$MACOS_SIGNING" in
|
|
||||||
notarized) macos="The macOS app is signed with a Developer ID and notarized by Apple." ;;
|
|
||||||
signed) macos="The macOS app is signed with a Developer ID but **not notarized**: the first time, right-click \`FieldCraft.app\` in Applications and choose **Open**." ;;
|
|
||||||
*) macos="The macOS app is **ad-hoc signed and not notarized**: macOS blocks the first launch. Right-click \`FieldCraft.app\` in Applications and choose **Open** (then **Open** again), or run \`xattr -dr com.apple.quarantine /Applications/FieldCraft.app\`." ;;
|
|
||||||
esac
|
|
||||||
awk -v v="$VERSION" -v m="$macos" '{ gsub(/\{version\}/, v); gsub(/\{macos_signing\}/, m); print }' \
|
|
||||||
.github/release-notes.md >notes.md
|
|
||||||
cat notes.md >>"$GITHUB_STEP_SUMMARY"
|
|
||||||
- name: Upload the dry-run artifacts
|
|
||||||
if: needs.version.outputs.draft != 'true'
|
|
||||||
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
||||||
with:
|
|
||||||
name: release-assets
|
|
||||||
path: |
|
|
||||||
artifacts/*
|
|
||||||
notes.md
|
|
||||||
if-no-files-found: error
|
|
||||||
- name: Create or update the draft release
|
|
||||||
if: needs.version.outputs.draft == 'true'
|
|
||||||
working-directory: artifacts
|
|
||||||
run: |
|
|
||||||
tag="v$VERSION"
|
|
||||||
title="FieldCraft v$VERSION"
|
|
||||||
if gh api "repos/$GH_REPO/git/matching-refs/tags/$tag" --jq '.[].ref' | grep -Fxq "refs/tags/$tag"; then
|
|
||||||
echo "::error::Tag $tag already exists. Choose a new version; never move a release tag."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if draft="$(gh release view "$tag" --json isDraft --jq .isDraft 2>/dev/null)"; then
|
|
||||||
if [ "$draft" != true ]; then
|
|
||||||
echo "::error::Release $tag is already published. Bump the version before releasing."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# A rebuild of the same version replaces the draft's assets (removing names it no longer
|
|
||||||
# makes); its notes are kept.
|
|
||||||
assets="$(gh release view "$tag" --json assets --jq '.assets[].name')"
|
|
||||||
while IFS= read -r asset; do
|
|
||||||
if [ -n "$asset" ]; then gh release delete-asset "$tag" "$asset" --yes; fi
|
|
||||||
done <<<"$assets"
|
|
||||||
gh release edit "$tag" --draft --title "$title" --target "$GITHUB_SHA" --prerelease="$PRERELEASE"
|
|
||||||
gh release upload "$tag" -- *
|
|
||||||
else
|
|
||||||
gh release create "$tag" --draft --title "$title" --target "$GITHUB_SHA" \
|
|
||||||
--notes-file ../notes.md --generate-notes --prerelease="$PRERELEASE" -- *
|
|
||||||
fi
|
|
||||||
echo "Draft release **$title** at \`${GITHUB_SHA::9}\`: $(gh release view "$tag" --json url --jq .url)" >>"$GITHUB_STEP_SUMMARY"
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
/target*/
|
|
||||||
/plan/
|
|
||||||
/dist/
|
|
||||||
/.agent-files/
|
|
||||||
/worktrees/
|
|
||||||
*~
|
|
||||||
.DS_Store
|
|
||||||
*.swp
|
|
||||||
__pycache__/
|
|
||||||
|
After Width: | Height: | Size: 72 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 37 KiB |
|
After Width: | Height: | Size: 113 KiB |
|
After Width: | Height: | Size: 127 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 64 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 295 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 220 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 204 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 42 KiB |