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
21 changes: 21 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,27 @@ Keep them dependency-light and runnable with a plain `python3`. They are
diagnostics, and a diagnostic that needs its own environment before it can tell
you anything tends not to get run.

## Releasing

A release is one pull request and one tag:

1. Set the new version in `Cargo.toml` and run `cargo build` so `Cargo.lock`
follows.
2. Turn `## [Unreleased]` in `CHANGELOG.md` into `## [X.Y.Z] - YYYY-MM-DD`,
keep an empty `## [Unreleased]` above it, and add the link line at the
bottom.
3. Set `version` and `date-released` in `CITATION.cff`.
4. Regenerate the example report with the commands in
[docs/about/contributing.md](../docs/about/contributing.md), so the website
shows the new version.
5. Merge, then push the tag `vX.Y.Z`. The release workflow builds the four
binaries and publishes the release, and Zenodo archives it with a DOI.

`tools/check_site.py` fails while `Cargo.toml`, `CITATION.cff`, the CHANGELOG
and the example report disagree on the version. The release workflow also runs
on any pull request that changes it, without publishing, so a broken build
shows up before the tag.

## Documentation

The website is plain HTML in `docs/` (`index.html`, `how-it-works.html`,
Expand Down
2 changes: 1 addition & 1 deletion .github/DISCUSSION_TEMPLATE/q-a.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ body:
attributes:
label: Version
description: The output of `recore --version`, plus the commit if you built from a branch.
placeholder: recore 0.2.0
placeholder: recore 1.0.0
validations:
required: true

Expand Down
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ body:
label: Recore version
description: >-
The output of `recore --version`. If you built from a branch rather than
a tag, add the commit too: there is one tag so far and `main` moves, so
the version string alone does not identify the code you ran.
placeholder: recore 0.2.0 (main, 4f9a1c2)
a release, add the commit too: `main` moves, so the version string alone
does not identify the code you ran.
placeholder: recore 1.0.0 (main, 4f9a1c2)
validations:
required: true

Expand Down
11 changes: 5 additions & 6 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@ you in the release notes unless you would rather stay anonymous.

| Version | Status |
|---------|--------|
| `main` (0.2.0 development line) | supported, fixes land here first |
| `v0.1.0` | the only tagged release so far |
| `1.0.x` | supported, fixes land here first |
| older than 1.0 | not supported: upgrade to the newest release |

Recore has exactly one tag today, so there is deliberately no "previous stable"
row in that table and no backport branch: there is nothing to backport to. A
security fix goes onto the development line and out in the next tag, and the
answer to "which version should I run" is the newest one.
There is deliberately no backport branch. A security fix goes onto `main` and
out in the next release, and the answer to "which version should I run" is the
newest one.

Nothing else is supported. In particular there is no Bioconda package, no
container image and no third-party build maintained by this project, so a binary
Expand Down
8 changes: 8 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ on:
- "docs/**"
- "README.md"
- "assets/**"
- "LICENSE"
- "CITATION.cff"
- "CHANGELOG.md"
- ".github/CONTRIBUTING.md"
- "src/**"
- "Cargo.toml"
- "Cargo.lock"
Expand All @@ -39,6 +43,10 @@ on:
- "docs/**"
- "README.md"
- "assets/**"
- "LICENSE"
- "CITATION.cff"
- "CHANGELOG.md"
- ".github/CONTRIBUTING.md"
- "src/**"
- "Cargo.toml"
- "Cargo.lock"
Expand Down
12 changes: 11 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
name: Build & Release

# A v* tag builds the four binaries and publishes the release. A pull request
# that changes this file, or a run by hand, builds them without publishing, so
# a broken build shows up before release day instead of on it.
on:
push:
tags: ["v*"]
pull_request:
paths:
- ".github/workflows/release.yml"
workflow_dispatch:

permissions:
contents: write
contents: read

jobs:
build:
Expand Down Expand Up @@ -57,7 +64,10 @@ jobs:

release:
needs: build
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: write
timeout-minutes: 15
steps:
- uses: actions/download-artifact@v8
Expand Down
18 changes: 16 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and Recore uses semantic versioning.

## [Unreleased]

## [1.0.0] - 2026-10-18

The first public release, under the GNU Affero General Public License v3.0.
Since 0.2.0, Recore also reads PPanGGOLiN, PanTA and PIRATE, needs five to seven
times less memory per genome, marks the cells it never searched instead of
calling them absent, and comes with a website and a report that explain every
decision. Every change, in detail:

### Fixed

- Memory no longer grows by megabytes with every genome. Each genome's
Expand Down Expand Up @@ -100,6 +108,11 @@ and Recore uses semantic versioning.
documentation. `tools/label_example_report.py` adds the note after the report
is regenerated, and `tools/check_site.py` fails on a report or a link without
it.
- The release workflow builds the four binaries on a pull request that changes
it, and by hand, without publishing anything; only a `v*` tag publishes, and
only that job can write to the repository. `tools/check_site.py` fails if
`Cargo.toml`, `CITATION.cff`, the CHANGELOG and the example report disagree
on the version.
- `benchmarks/performance_benchmark.py` times Recore on any pangenome, given
the same inputs as Recore, with an optional tree to keep a subset of genomes
and a cluster limit for a quick run. It replaces a benchmark that only ran on
Expand Down Expand Up @@ -722,6 +735,7 @@ and Recore uses semantic versioning.
preset, thread count, and output directory.
- CI and release workflow scaffolding.

[Unreleased]: https://github.com/PathoGenOmics-Lab/recore/compare/0.2.0...HEAD
[0.2.0]: https://github.com/PathoGenOmics-Lab/recore/compare/v0.1.0...0.2.0
[Unreleased]: https://github.com/PathoGenOmics-Lab/recore/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/PathoGenOmics-Lab/recore/compare/v0.2.0...v1.0.0
[0.2.0]: https://github.com/PathoGenOmics-Lab/recore/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/PathoGenOmics-Lab/recore/releases/tag/v0.1.0
2 changes: 2 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ authors:
affiliation: "I2SysBio, University of Valencia-CSIC, FISABIO Joint Research Unit Infection and Public Health, Valencia, Spain"
repository-code: "https://github.com/PathoGenOmics-Lab/recore"
url: "https://pathogenomics-lab.github.io/recore/"
version: 1.0.0
date-released: "2026-10-18"
license: AGPL-3.0-only
keywords:
- pangenome
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "recore"
version = "0.2.0"
version = "1.0.0"
edition = "2021"
rust-version = "1.85"
authors = ["Paula Ruiz-Rodriguez <paula.ruiz.rodriguez@csic.es>", "Mireia Coscolla"]
Expand Down
6 changes: 3 additions & 3 deletions docs/assets/example-report.html

Large diffs are not rendered by default.

28 changes: 26 additions & 2 deletions tools/check_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
contributing guide and the website name the same one;
synthetic the example report says its data are made up, next to its title,
and so does every link to it;
version the version in Cargo.toml is the one CITATION.cff and the example
report carry, and the CHANGELOG has a section and a link for it;
dashes no em-dashes;
try with --run-tutorial, the "Try it" commands are run as written and
summary.txt must give the numbers the page promises.
Expand Down Expand Up @@ -463,6 +465,28 @@ def check_synthetic(pages: dict[str, Page]) -> list[str]:
return problems


def check_versions() -> list[str]:
"""A release names one version: Cargo.toml's, also in CITATION.cff, in the
CHANGELOG and in the example report the website shows."""
version = re.search(r'^version\s*=\s*"([^"]+)"', Path("Cargo.toml").read_text(encoding="utf-8"), flags=re.M).group(1)
problems = []
cff = re.search(r"^version:\s*([\w.-]+)", Path("CITATION.cff").read_text(encoding="utf-8"), flags=re.M)
if not cff or cff.group(1) != version:
problems.append(f"CITATION.cff: version is {cff.group(1) if cff else 'missing'}, Cargo.toml says {version}")
changelog = Path("CHANGELOG.md").read_text(encoding="utf-8")
if not re.search(rf"^## \[{re.escape(version)}\] - \d{{4}}-\d{{2}}-\d{{2}}$", changelog, flags=re.M):
problems.append(f"CHANGELOG.md: no dated '## [{version}]' section for the version in Cargo.toml")
if not re.search(rf"^\[{re.escape(version)}\]: https://", changelog, flags=re.M):
problems.append(f"CHANGELOG.md: no link line for [{version}] at the bottom")
shown = re.search(r"<meta name='generator' content='Recore v([^']+)'>", EXAMPLE_REPORT.read_text(encoding="utf-8"))
if not shown or shown.group(1) != version:
problems.append(
f"{EXAMPLE_REPORT}: made by Recore {shown.group(1) if shown else 'unknown'}, Cargo.toml says {version}; "
"regenerate it (docs/about/contributing.md has the commands)"
)
return problems


def check_dashes(pages: dict[str, Page]) -> list[str]:
problems = []
for path in [SITE / p for p in pages] + SCRIPTS:
Expand Down Expand Up @@ -528,7 +552,7 @@ def main() -> int:
pages = all_pages()
front = {name: pages[name] for name in PAGES}
problems = check_docs_built() + check_links(pages) + check_flags(front, args.recore) + check_walkthrough() + check_readme(pages, args.recore)
problems += check_licence(pages) + check_synthetic(pages) + check_dashes(pages)
problems += check_licence(pages) + check_synthetic(pages) + check_versions() + check_dashes(pages)
if args.run_tutorial:
if not shutil.which("minimap2"):
problems.append("Try it: minimap2 is not on PATH")
Expand All @@ -539,7 +563,7 @@ def main() -> int:
for problem in problems:
print(f" {problem}", file=sys.stderr)
return 1
checked = "generated pages, links, options, defaults, walkthrough, README, licence, synthetic data, dashes" + (", and the Try-it run" if args.run_tutorial else "")
checked = "generated pages, links, options, defaults, walkthrough, README, licence, synthetic data, versions, dashes" + (", and the Try-it run" if args.run_tutorial else "")
print(f"docs/: {checked} all agree with the code")
return 0

Expand Down
Loading