Replidec 0.3.4__tar.gz → 0.3.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- replidec-0.3.6/.conda/meta.yaml +42 -0
- replidec-0.3.6/.gitattributes +4 -0
- replidec-0.3.6/.github/CODEOWNERS +2 -0
- replidec-0.3.6/.github/ISSUE_TEMPLATE.md +15 -0
- replidec-0.3.6/.github/pull_request_template.md +50 -0
- replidec-0.3.6/.github/workflows/release.yml +386 -0
- replidec-0.3.6/.github/workflows/test.yml +170 -0
- replidec-0.3.6/.gitignore +8 -0
- replidec-0.3.6/.pre-commit-config.yaml +11 -0
- replidec-0.3.6/AGENTS.md +29 -0
- replidec-0.3.6/CONTRIBUTING.md +92 -0
- replidec-0.3.6/Dockerfile +19 -0
- {replidec-0.3.4 → replidec-0.3.6}/MANIFEST.in +2 -1
- replidec-0.3.6/PKG-INFO +242 -0
- replidec-0.3.6/README.md +223 -0
- replidec-0.3.6/README.rst +223 -0
- replidec-0.3.6/README.rst2 +25 -0
- replidec-0.3.6/RELEASING.md +65 -0
- replidec-0.3.6/Replidec/Replidec.py +346 -0
- replidec-0.3.6/Replidec/Replidec_cmdline.py +118 -0
- replidec-0.3.6/Replidec/Replidec_multi.py +287 -0
- {replidec-0.3.4 → replidec-0.3.6}/Replidec/__init__.py +2 -6
- replidec-0.3.6/Replidec/utility.py +36 -0
- replidec-0.3.6/Replidec.egg-info/PKG-INFO +242 -0
- {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/SOURCES.txt +22 -1
- {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/entry_points.txt +1 -0
- replidec-0.3.6/code_review.md +65 -0
- replidec-0.3.6/replidec_banner.jpg +0 -0
- replidec-0.3.6/requirements-dev.txt +2 -0
- replidec-0.3.6/requirements.txt +10 -0
- replidec-0.3.6/scripts/check_release_version.py +54 -0
- replidec-0.3.6/scripts/update_bioconda_recipe.py +141 -0
- replidec-0.3.6/setup.cfg +16 -0
- replidec-0.3.6/setup.py +53 -0
- replidec-0.3.6/test/example/example.small.list +4 -0
- replidec-0.3.6/test/example/genome_test.small.index +4 -0
- replidec-0.3.6/test/example.sh +65 -0
- replidec-0.3.6/test/test_release_tools.py +121 -0
- replidec-0.3.4/PKG-INFO +0 -190
- replidec-0.3.4/README.rst +0 -158
- replidec-0.3.4/Replidec/Replidec.py +0 -573
- replidec-0.3.4/Replidec/Replidec_cmdline.py +0 -96
- replidec-0.3.4/Replidec/Replidec_multi.py +0 -201
- replidec-0.3.4/Replidec/cli.py +0 -82
- replidec-0.3.4/Replidec/utility.py +0 -28
- replidec-0.3.4/Replidec.egg-info/PKG-INFO +0 -190
- replidec-0.3.4/setup.cfg +0 -23
- replidec-0.3.4/setup.py +0 -36
- replidec-0.3.4/test/example/example.small.list +0 -10
- replidec-0.3.4/test/example/genome_test.small.index +0 -10
- replidec-0.3.4/test/example.sh +0 -7
- {replidec-0.3.4 → replidec-0.3.6}/LICENSE +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/dependency_links.txt +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/requires.txt +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/top_level.txt +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/zip-safe +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/example.list +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/generate.sh +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaab +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaac +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaad +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaae +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaf +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaag +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaah +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaai +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaj +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaak +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaal +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaam +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaan +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaao +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaap +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaq +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test.index +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/mock_data_single_lifestyleBC.py +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.1.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.10.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.11.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.12.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.13.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.14.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.15.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.16.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.17.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.18.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.19.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.2.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.20.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.21.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.22.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.3.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.4.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.5.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.6.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.7.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.8.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.9.faa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/test.contig.small.fa +0 -0
- {replidec-0.3.4 → replidec-0.3.6}/test/example/test.contig.small.new.fa +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{% set name = "Replidec" %}
|
|
2
|
+
{% set version = "0.2.3.1" %}
|
|
3
|
+
|
|
4
|
+
package:
|
|
5
|
+
name: "{{ name|lower }}"
|
|
6
|
+
version: "{{ version }}"
|
|
7
|
+
|
|
8
|
+
source:
|
|
9
|
+
path: "../"
|
|
10
|
+
|
|
11
|
+
build:
|
|
12
|
+
number: 0
|
|
13
|
+
entry_points:
|
|
14
|
+
- Replidec=Replidec.Replidec_cmdline:main
|
|
15
|
+
script: "pip install . -vv"
|
|
16
|
+
|
|
17
|
+
requirements:
|
|
18
|
+
host:
|
|
19
|
+
- python=3.10
|
|
20
|
+
- biopython=1.79
|
|
21
|
+
- click
|
|
22
|
+
- numpy=1.23.1
|
|
23
|
+
- pip
|
|
24
|
+
run:
|
|
25
|
+
- python=3.10
|
|
26
|
+
- biopython=1.79
|
|
27
|
+
- click
|
|
28
|
+
- numpy=1.23.1
|
|
29
|
+
- mmseqs2
|
|
30
|
+
- blast
|
|
31
|
+
- hmmer
|
|
32
|
+
- prodigal
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
about:
|
|
36
|
+
home: "https://github.com/deng-lab/Replidec"
|
|
37
|
+
license: MIT
|
|
38
|
+
license_family: MIT
|
|
39
|
+
license_file:
|
|
40
|
+
summary: "Replidec"
|
|
41
|
+
doc_url:
|
|
42
|
+
dev_url:
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
Replidec/db/mmseq2_linclust_cluster.stat.scoreOpt.tsv filter=lfs diff=lfs merge=lfs -text
|
|
2
|
+
Replidec/db/bayes_mmseqs_index/all.protein filter=lfs diff=lfs merge=lfs -text
|
|
3
|
+
Replidec/db/bayes_mmseqs_index/all.protein_h filter=lfs diff=lfs merge=lfs -text
|
|
4
|
+
Replidec/db/bayes_mmseqs_index/all.protein.lookup filter=lfs diff=lfs merge=lfs -text
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
* Replidec version:
|
|
2
|
+
* Python version:
|
|
3
|
+
* Operating System:
|
|
4
|
+
|
|
5
|
+
### Description
|
|
6
|
+
|
|
7
|
+
Describe what you were trying to get done.
|
|
8
|
+
Tell us what happened, what went wrong, and what you expected to happen.
|
|
9
|
+
|
|
10
|
+
### What I Did
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Paste the command(s) you ran and the output.
|
|
14
|
+
If there was a crash, please include the traceback here.
|
|
15
|
+
```
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What changed? Keep this short and specific. -->
|
|
4
|
+
|
|
5
|
+
## Motivation
|
|
6
|
+
|
|
7
|
+
<!-- Why is the change needed? Link the relevant issue or discussion. -->
|
|
8
|
+
|
|
9
|
+
## Branch intent
|
|
10
|
+
|
|
11
|
+
- [ ] `develop` to `main` release candidate
|
|
12
|
+
- [ ] Optional feature branch to `develop`
|
|
13
|
+
- [ ] Other (explain below)
|
|
14
|
+
|
|
15
|
+
## Architecture, scientific behavior, and compatibility
|
|
16
|
+
|
|
17
|
+
<!--
|
|
18
|
+
Explain how the change fits the existing design. Call out intentional changes
|
|
19
|
+
to scientific logic, thresholds, database assumptions, CLI behavior, file
|
|
20
|
+
formats, outputs, dependencies, or supported environments. Write "No impact"
|
|
21
|
+
for areas that are unaffected.
|
|
22
|
+
-->
|
|
23
|
+
|
|
24
|
+
## Validation
|
|
25
|
+
|
|
26
|
+
<!-- List the exact commands or workflows run and summarize their results. -->
|
|
27
|
+
|
|
28
|
+
```text
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Regression risks and review focus
|
|
33
|
+
|
|
34
|
+
<!-- What could this change break, and where should reviewers look closely? -->
|
|
35
|
+
|
|
36
|
+
## Release impact
|
|
37
|
+
|
|
38
|
+
- [ ] No production release is required.
|
|
39
|
+
- [ ] A production release is appropriate after this PR is approved and merged.
|
|
40
|
+
- [ ] The package version, documentation, or release notes need updating.
|
|
41
|
+
|
|
42
|
+
## Author checklist
|
|
43
|
+
|
|
44
|
+
- [ ] The change is focused and contains no unrelated modifications.
|
|
45
|
+
- [ ] New or changed behavior has appropriate tests.
|
|
46
|
+
- [ ] Existing behavior and backward compatibility were checked.
|
|
47
|
+
- [ ] Flake8 and relevant tests pass, or failures are explained above.
|
|
48
|
+
- [ ] No secrets, generated artifacts, unpublished data, or private URLs are included.
|
|
49
|
+
- [ ] Codex review findings have been resolved or answered.
|
|
50
|
+
- [ ] The pull request is ready for final human review.
|
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*.*.*"
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
ref:
|
|
10
|
+
description: Branch or commit to validate during a dry run
|
|
11
|
+
required: true
|
|
12
|
+
default: main
|
|
13
|
+
type: string
|
|
14
|
+
tag:
|
|
15
|
+
description: Expected release tag in vX.Y.Z format
|
|
16
|
+
required: true
|
|
17
|
+
type: string
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
|
|
22
|
+
concurrency:
|
|
23
|
+
group: release-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
|
|
24
|
+
cancel-in-progress: false
|
|
25
|
+
|
|
26
|
+
jobs:
|
|
27
|
+
validate:
|
|
28
|
+
name: Validate release metadata
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
outputs:
|
|
31
|
+
checkout-ref: ${{ steps.mode.outputs.checkout-ref }}
|
|
32
|
+
tag: ${{ steps.version.outputs.tag }}
|
|
33
|
+
version: ${{ steps.version.outputs.version }}
|
|
34
|
+
steps:
|
|
35
|
+
- name: Resolve release mode
|
|
36
|
+
id: mode
|
|
37
|
+
shell: bash
|
|
38
|
+
env:
|
|
39
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
40
|
+
PUSH_TAG: ${{ github.ref_name }}
|
|
41
|
+
INPUT_REF: ${{ inputs.ref }}
|
|
42
|
+
INPUT_TAG: ${{ inputs.tag }}
|
|
43
|
+
run: |
|
|
44
|
+
set -euo pipefail
|
|
45
|
+
|
|
46
|
+
if [[ "${EVENT_NAME}" == "push" ]]; then
|
|
47
|
+
tag="${PUSH_TAG}"
|
|
48
|
+
checkout_ref="${PUSH_TAG}"
|
|
49
|
+
else
|
|
50
|
+
tag="${INPUT_TAG}"
|
|
51
|
+
checkout_ref="${INPUT_REF}"
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
if [[ "${tag}" == *$'\n'* || "${tag}" == *$'\r'* ||
|
|
55
|
+
"${checkout_ref}" == *$'\n'* || "${checkout_ref}" == *$'\r'* ]]; then
|
|
56
|
+
echo "Release tag and checkout ref must each be a single line." >&2
|
|
57
|
+
exit 1
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
printf 'checkout-ref=%s\n' "${checkout_ref}" >> "${GITHUB_OUTPUT}"
|
|
61
|
+
printf 'tag=%s\n' "${tag}" >> "${GITHUB_OUTPUT}"
|
|
62
|
+
|
|
63
|
+
- name: Check out the release candidate
|
|
64
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
65
|
+
with:
|
|
66
|
+
ref: ${{ steps.mode.outputs.checkout-ref }}
|
|
67
|
+
fetch-depth: 0
|
|
68
|
+
|
|
69
|
+
- name: Validate tag and project version
|
|
70
|
+
id: version
|
|
71
|
+
shell: bash
|
|
72
|
+
env:
|
|
73
|
+
RELEASE_TAG: ${{ steps.mode.outputs.tag }}
|
|
74
|
+
PUBLISH: ${{ github.event_name == 'push' }}
|
|
75
|
+
run: |
|
|
76
|
+
set -euo pipefail
|
|
77
|
+
python scripts/check_release_version.py \
|
|
78
|
+
--tag "${RELEASE_TAG}" \
|
|
79
|
+
--github-output "${GITHUB_OUTPUT}"
|
|
80
|
+
|
|
81
|
+
if [[ "${PUBLISH}" == "true" ]]; then
|
|
82
|
+
tag_commit="$(git rev-list -n 1 "refs/tags/${RELEASE_TAG}")"
|
|
83
|
+
checkout_commit="$(git rev-parse HEAD)"
|
|
84
|
+
if [[ "${tag_commit}" != "${checkout_commit}" ]]; then
|
|
85
|
+
echo "Release tag ${RELEASE_TAG} does not point to the checked-out commit" >&2
|
|
86
|
+
exit 1
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
git fetch --no-tags origin main:refs/remotes/origin/main
|
|
90
|
+
if ! git merge-base --is-ancestor "${tag_commit}" origin/main; then
|
|
91
|
+
echo "Release tag ${RELEASE_TAG} does not point to a commit in main" >&2
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
fi
|
|
95
|
+
|
|
96
|
+
test:
|
|
97
|
+
name: Test release candidate
|
|
98
|
+
needs: validate
|
|
99
|
+
uses: ./.github/workflows/test.yml
|
|
100
|
+
with:
|
|
101
|
+
ref: ${{ needs.validate.outputs.checkout-ref }}
|
|
102
|
+
permissions:
|
|
103
|
+
contents: read
|
|
104
|
+
|
|
105
|
+
build:
|
|
106
|
+
name: Build and verify Python distributions
|
|
107
|
+
needs:
|
|
108
|
+
- validate
|
|
109
|
+
- test
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
timeout-minutes: 20
|
|
112
|
+
steps:
|
|
113
|
+
- name: Check out the tested release candidate
|
|
114
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
115
|
+
with:
|
|
116
|
+
ref: ${{ needs.validate.outputs.checkout-ref }}
|
|
117
|
+
|
|
118
|
+
- name: Set up Python
|
|
119
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
120
|
+
with:
|
|
121
|
+
python-version: "3.10"
|
|
122
|
+
cache: pip
|
|
123
|
+
|
|
124
|
+
- name: Build sdist and wheel
|
|
125
|
+
env:
|
|
126
|
+
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
|
|
127
|
+
run: |
|
|
128
|
+
set -euo pipefail
|
|
129
|
+
python -m pip install --upgrade build twine
|
|
130
|
+
python -m build
|
|
131
|
+
python -m twine check dist/*
|
|
132
|
+
|
|
133
|
+
python - <<'PY'
|
|
134
|
+
import os
|
|
135
|
+
from pathlib import Path
|
|
136
|
+
|
|
137
|
+
version = os.environ["RELEASE_VERSION"]
|
|
138
|
+
files = [path.name.lower() for path in Path("dist").iterdir()]
|
|
139
|
+
expected = f"replidec-{version}"
|
|
140
|
+
if len(files) != 2 or not all(expected in filename for filename in files):
|
|
141
|
+
raise SystemExit(f"Unexpected distribution files: {files}")
|
|
142
|
+
print("Verified distribution files:", *files)
|
|
143
|
+
PY
|
|
144
|
+
|
|
145
|
+
- name: Install and smoke-test the wheel
|
|
146
|
+
run: |
|
|
147
|
+
set -euo pipefail
|
|
148
|
+
python -m pip install --force-reinstall dist/*.whl
|
|
149
|
+
Replidec --version
|
|
150
|
+
replidec --help >/dev/null
|
|
151
|
+
|
|
152
|
+
- name: Upload immutable Python distributions
|
|
153
|
+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
154
|
+
with:
|
|
155
|
+
name: python-dist-${{ needs.validate.outputs.version }}
|
|
156
|
+
path: dist/
|
|
157
|
+
if-no-files-found: error
|
|
158
|
+
retention-days: 30
|
|
159
|
+
|
|
160
|
+
publish_pypi:
|
|
161
|
+
name: Publish to PyPI
|
|
162
|
+
if: github.event_name == 'push'
|
|
163
|
+
needs:
|
|
164
|
+
- validate
|
|
165
|
+
- build
|
|
166
|
+
- bioconda_preflight
|
|
167
|
+
runs-on: ubuntu-latest
|
|
168
|
+
environment:
|
|
169
|
+
name: pypi
|
|
170
|
+
url: https://pypi.org/p/replidec
|
|
171
|
+
permissions:
|
|
172
|
+
contents: read
|
|
173
|
+
id-token: write
|
|
174
|
+
steps:
|
|
175
|
+
- name: Download tested distributions
|
|
176
|
+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
177
|
+
with:
|
|
178
|
+
name: python-dist-${{ needs.validate.outputs.version }}
|
|
179
|
+
path: dist
|
|
180
|
+
|
|
181
|
+
- name: Publish distributions with PyPI Trusted Publishing
|
|
182
|
+
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
|
|
183
|
+
with:
|
|
184
|
+
packages-dir: dist/
|
|
185
|
+
skip-existing: true
|
|
186
|
+
|
|
187
|
+
bioconda_preflight:
|
|
188
|
+
name: Check Bioconda PR access
|
|
189
|
+
if: github.event_name == 'push'
|
|
190
|
+
needs:
|
|
191
|
+
- validate
|
|
192
|
+
- test
|
|
193
|
+
runs-on: ubuntu-latest
|
|
194
|
+
environment:
|
|
195
|
+
name: bioconda
|
|
196
|
+
url: https://github.com/bioconda/bioconda-recipes/pulls
|
|
197
|
+
permissions:
|
|
198
|
+
contents: read
|
|
199
|
+
env:
|
|
200
|
+
GH_TOKEN: ${{ secrets.BIOCONDA_PR_TOKEN }}
|
|
201
|
+
FORK_OWNER: ${{ vars.BIOCONDA_FORK_OWNER || github.repository_owner }}
|
|
202
|
+
steps:
|
|
203
|
+
- name: Verify token and fork access before publishing
|
|
204
|
+
run: |
|
|
205
|
+
set -euo pipefail
|
|
206
|
+
if [[ -z "${GH_TOKEN}" ]]; then
|
|
207
|
+
echo "BIOCONDA_PR_TOKEN is not configured in the bioconda environment." >&2
|
|
208
|
+
exit 1
|
|
209
|
+
fi
|
|
210
|
+
|
|
211
|
+
gh auth status
|
|
212
|
+
token_owner="$(gh api user --jq '.login')"
|
|
213
|
+
fork="${FORK_OWNER}/bioconda-recipes"
|
|
214
|
+
fork_access="$(gh api "repos/${fork}" \
|
|
215
|
+
--jq '[(.permissions.push // false), (.fork // false), (.parent.full_name // "")] | @tsv')"
|
|
216
|
+
IFS=$'\t' read -r can_push is_fork parent_repo <<< "${fork_access}"
|
|
217
|
+
|
|
218
|
+
if [[ "${is_fork}" != "true" || "${parent_repo}" != "bioconda/bioconda-recipes" ]]; then
|
|
219
|
+
echo "${fork} is not a fork of bioconda/bioconda-recipes." >&2
|
|
220
|
+
exit 1
|
|
221
|
+
fi
|
|
222
|
+
|
|
223
|
+
if [[ "${can_push}" != "true" ]]; then
|
|
224
|
+
echo "BIOCONDA_PR_TOKEN (${token_owner}) does not have push access to ${fork}." >&2
|
|
225
|
+
exit 1
|
|
226
|
+
fi
|
|
227
|
+
|
|
228
|
+
probe_branch="replidec-preflight-${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}-missing"
|
|
229
|
+
if gh api "repos/${fork}/git/ref/heads/${probe_branch}" >/dev/null 2>&1; then
|
|
230
|
+
echo "Refusing to use existing permission-probe branch ${probe_branch}." >&2
|
|
231
|
+
exit 1
|
|
232
|
+
fi
|
|
233
|
+
|
|
234
|
+
set +e
|
|
235
|
+
probe_output="$(gh api \
|
|
236
|
+
--include \
|
|
237
|
+
--method POST \
|
|
238
|
+
repos/bioconda/bioconda-recipes/pulls \
|
|
239
|
+
-f title="RepliDec release permission probe" \
|
|
240
|
+
-f head="${FORK_OWNER}:${probe_branch}" \
|
|
241
|
+
-f base=master \
|
|
242
|
+
2>&1)"
|
|
243
|
+
probe_exit=$?
|
|
244
|
+
set -e
|
|
245
|
+
|
|
246
|
+
if [[ ${probe_exit} -eq 0 ]] || ! grep -Eq '^HTTP/[^ ]+ 422 ' <<< "${probe_output}"; then
|
|
247
|
+
echo "BIOCONDA_PR_TOKEN (${token_owner}) cannot create pull requests in bioconda/bioconda-recipes." >&2
|
|
248
|
+
printf '%s\n' "${probe_output}" >&2
|
|
249
|
+
exit 1
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
{
|
|
253
|
+
echo "BIOCONDA_PR_TOKEN (${token_owner}) can push to ${fork}."
|
|
254
|
+
echo "The token can also reach the upstream pull-request creation endpoint."
|
|
255
|
+
} >> "${GITHUB_STEP_SUMMARY}"
|
|
256
|
+
|
|
257
|
+
github_release:
|
|
258
|
+
name: Create GitHub Release
|
|
259
|
+
if: github.event_name == 'push'
|
|
260
|
+
needs:
|
|
261
|
+
- validate
|
|
262
|
+
- build
|
|
263
|
+
- publish_pypi
|
|
264
|
+
runs-on: ubuntu-latest
|
|
265
|
+
permissions:
|
|
266
|
+
contents: write
|
|
267
|
+
steps:
|
|
268
|
+
- name: Download tested distributions
|
|
269
|
+
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
|
|
270
|
+
with:
|
|
271
|
+
name: python-dist-${{ needs.validate.outputs.version }}
|
|
272
|
+
path: dist
|
|
273
|
+
|
|
274
|
+
- name: Create or update the release
|
|
275
|
+
env:
|
|
276
|
+
GH_TOKEN: ${{ github.token }}
|
|
277
|
+
GH_REPO: ${{ github.repository }}
|
|
278
|
+
RELEASE_TAG: ${{ needs.validate.outputs.tag }}
|
|
279
|
+
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
|
|
280
|
+
run: |
|
|
281
|
+
set -euo pipefail
|
|
282
|
+
if gh release view "${RELEASE_TAG}" >/dev/null 2>&1; then
|
|
283
|
+
gh release upload "${RELEASE_TAG}" dist/* --clobber
|
|
284
|
+
else
|
|
285
|
+
gh release create "${RELEASE_TAG}" dist/* \
|
|
286
|
+
--verify-tag \
|
|
287
|
+
--generate-notes \
|
|
288
|
+
--title "RepliDec ${RELEASE_VERSION}"
|
|
289
|
+
fi
|
|
290
|
+
|
|
291
|
+
bioconda_pr:
|
|
292
|
+
name: Open Bioconda recipe PR
|
|
293
|
+
if: github.event_name == 'push'
|
|
294
|
+
needs:
|
|
295
|
+
- validate
|
|
296
|
+
- github_release
|
|
297
|
+
runs-on: ubuntu-latest
|
|
298
|
+
timeout-minutes: 20
|
|
299
|
+
environment:
|
|
300
|
+
name: bioconda
|
|
301
|
+
url: https://github.com/bioconda/bioconda-recipes/pulls
|
|
302
|
+
permissions:
|
|
303
|
+
contents: read
|
|
304
|
+
env:
|
|
305
|
+
GH_TOKEN: ${{ secrets.BIOCONDA_PR_TOKEN }}
|
|
306
|
+
FORK_OWNER: ${{ vars.BIOCONDA_FORK_OWNER || github.repository_owner }}
|
|
307
|
+
RELEASE_TAG: ${{ needs.validate.outputs.tag }}
|
|
308
|
+
RELEASE_VERSION: ${{ needs.validate.outputs.version }}
|
|
309
|
+
steps:
|
|
310
|
+
- name: Check out release automation
|
|
311
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
312
|
+
with:
|
|
313
|
+
ref: ${{ needs.validate.outputs.checkout-ref }}
|
|
314
|
+
|
|
315
|
+
- name: Download the published PyPI sdist and compute its checksum
|
|
316
|
+
id: sdist
|
|
317
|
+
run: |
|
|
318
|
+
set -euo pipefail
|
|
319
|
+
sdist="${RUNNER_TEMP}/replidec-${RELEASE_VERSION}.tar.gz"
|
|
320
|
+
url="https://pypi.org/packages/source/r/replidec/replidec-${RELEASE_VERSION}.tar.gz"
|
|
321
|
+
curl --fail --location \
|
|
322
|
+
--retry 12 \
|
|
323
|
+
--retry-delay 10 \
|
|
324
|
+
--retry-all-errors \
|
|
325
|
+
--output "${sdist}" \
|
|
326
|
+
"${url}"
|
|
327
|
+
sha256="$(sha256sum "${sdist}" | cut -d ' ' -f 1)"
|
|
328
|
+
echo "sha256=${sha256}" >> "${GITHUB_OUTPUT}"
|
|
329
|
+
|
|
330
|
+
- name: Update the official Bioconda recipe
|
|
331
|
+
env:
|
|
332
|
+
SDIST_SHA256: ${{ steps.sdist.outputs.sha256 }}
|
|
333
|
+
run: |
|
|
334
|
+
set -euo pipefail
|
|
335
|
+
fork="${FORK_OWNER}/bioconda-recipes"
|
|
336
|
+
branch="replidec-${RELEASE_VERSION}"
|
|
337
|
+
checkout="${RUNNER_TEMP}/bioconda-recipes"
|
|
338
|
+
|
|
339
|
+
if ! gh repo view "${fork}" >/dev/null 2>&1; then
|
|
340
|
+
echo "Missing ${fork}. Create a fork of bioconda/bioconda-recipes before publishing." >&2
|
|
341
|
+
exit 1
|
|
342
|
+
fi
|
|
343
|
+
|
|
344
|
+
gh auth setup-git
|
|
345
|
+
git clone --filter=blob:none "https://github.com/${fork}.git" "${checkout}"
|
|
346
|
+
cd "${checkout}"
|
|
347
|
+
git remote add upstream https://github.com/bioconda/bioconda-recipes.git
|
|
348
|
+
git fetch upstream master
|
|
349
|
+
git checkout -B "${branch}" upstream/master
|
|
350
|
+
|
|
351
|
+
python "${GITHUB_WORKSPACE}/scripts/update_bioconda_recipe.py" \
|
|
352
|
+
--recipe recipes/replidec/meta.yaml \
|
|
353
|
+
--version "${RELEASE_VERSION}" \
|
|
354
|
+
--sha256 "${SDIST_SHA256}"
|
|
355
|
+
|
|
356
|
+
if git diff --quiet -- recipes/replidec/meta.yaml; then
|
|
357
|
+
echo "Bioconda recipe is already up to date for ${RELEASE_VERSION}." >> "${GITHUB_STEP_SUMMARY}"
|
|
358
|
+
exit 0
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
git config user.name "RepliDec release bot"
|
|
362
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
363
|
+
git add recipes/replidec/meta.yaml
|
|
364
|
+
git commit -m "Update replidec to ${RELEASE_VERSION}"
|
|
365
|
+
git push --force origin "${branch}"
|
|
366
|
+
|
|
367
|
+
pr_url="$(gh api \
|
|
368
|
+
--method GET \
|
|
369
|
+
repos/bioconda/bioconda-recipes/pulls \
|
|
370
|
+
-f state=open \
|
|
371
|
+
-f base=master \
|
|
372
|
+
-f head="${FORK_OWNER}:${branch}" \
|
|
373
|
+
--jq '.[0].html_url // empty')"
|
|
374
|
+
|
|
375
|
+
if [[ -z "${pr_url}" ]]; then
|
|
376
|
+
pr_url="$(gh api \
|
|
377
|
+
--method POST \
|
|
378
|
+
repos/bioconda/bioconda-recipes/pulls \
|
|
379
|
+
-f base=master \
|
|
380
|
+
-f head="${FORK_OWNER}:${branch}" \
|
|
381
|
+
-f title="Update replidec to ${RELEASE_VERSION}" \
|
|
382
|
+
-f body="Automated recipe update for [RepliDec ${RELEASE_VERSION}](https://github.com/${GITHUB_REPOSITORY}/releases/tag/${RELEASE_TAG}). The source checksum was calculated from the published PyPI sdist." \
|
|
383
|
+
--jq '.html_url')"
|
|
384
|
+
fi
|
|
385
|
+
|
|
386
|
+
echo "Bioconda PR: ${pr_url}" >> "${GITHUB_STEP_SUMMARY}"
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- develop
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
workflow_call:
|
|
11
|
+
inputs:
|
|
12
|
+
ref:
|
|
13
|
+
description: Git ref to test; defaults to the triggering ref
|
|
14
|
+
required: false
|
|
15
|
+
type: string
|
|
16
|
+
workflow_dispatch:
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
|
|
21
|
+
concurrency:
|
|
22
|
+
group: test-${{ github.workflow }}-${{ github.event.pull_request.number || inputs.ref || github.ref }}
|
|
23
|
+
cancel-in-progress: true
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
lint:
|
|
27
|
+
name: Flake8
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
timeout-minutes: 10
|
|
30
|
+
steps:
|
|
31
|
+
- name: Check out candidate code
|
|
32
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
33
|
+
with:
|
|
34
|
+
ref: ${{ inputs.ref || github.sha }}
|
|
35
|
+
|
|
36
|
+
- name: Set up Python
|
|
37
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
|
|
38
|
+
with:
|
|
39
|
+
python-version: "3.10"
|
|
40
|
+
cache: pip
|
|
41
|
+
cache-dependency-path: requirements-dev.txt
|
|
42
|
+
|
|
43
|
+
- name: Install lint dependencies
|
|
44
|
+
run: python -m pip install --requirement requirements-dev.txt
|
|
45
|
+
|
|
46
|
+
- name: Run Flake8
|
|
47
|
+
run: python -m flake8 .
|
|
48
|
+
|
|
49
|
+
integration:
|
|
50
|
+
name: RepliDec integration
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
timeout-minutes: 90
|
|
53
|
+
defaults:
|
|
54
|
+
run:
|
|
55
|
+
shell: bash -leo pipefail {0}
|
|
56
|
+
|
|
57
|
+
steps:
|
|
58
|
+
- name: Check out candidate code
|
|
59
|
+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
|
60
|
+
with:
|
|
61
|
+
ref: ${{ inputs.ref || github.sha }}
|
|
62
|
+
|
|
63
|
+
- name: Install the current Bioconda package and runtime dependencies
|
|
64
|
+
uses: mamba-org/setup-micromamba@add3a49764cedee8ee24e82dfde87f5bc2914462 # v2.0.7
|
|
65
|
+
with:
|
|
66
|
+
environment-name: replidec-ci
|
|
67
|
+
create-args: >-
|
|
68
|
+
python=3.10
|
|
69
|
+
pip
|
|
70
|
+
replidec
|
|
71
|
+
condarc: |
|
|
72
|
+
channels:
|
|
73
|
+
- conda-forge
|
|
74
|
+
- bioconda
|
|
75
|
+
channel_priority: strict
|
|
76
|
+
cache-downloads: true
|
|
77
|
+
init-shell: bash
|
|
78
|
+
|
|
79
|
+
- name: Upgrade RepliDec to the candidate code
|
|
80
|
+
id: candidate
|
|
81
|
+
run: |
|
|
82
|
+
python -m pip install --no-deps --upgrade --force-reinstall .
|
|
83
|
+
|
|
84
|
+
(
|
|
85
|
+
cd "${RUNNER_TEMP}"
|
|
86
|
+
python - <<'PY'
|
|
87
|
+
import os
|
|
88
|
+
import re
|
|
89
|
+
from pathlib import Path
|
|
90
|
+
|
|
91
|
+
import Replidec
|
|
92
|
+
from Replidec.Replidec import DATABASE_MANIFEST
|
|
93
|
+
|
|
94
|
+
workspace = Path(os.environ["GITHUB_WORKSPACE"]).resolve()
|
|
95
|
+
source = (workspace / "Replidec/__init__.py").read_text(encoding="utf-8")
|
|
96
|
+
expected = re.search(r'^__version__\s*=\s*["\x27]([^"\x27]+)["\x27]', source, re.MULTILINE)
|
|
97
|
+
assert expected is not None, "Unable to read the candidate version"
|
|
98
|
+
|
|
99
|
+
package_path = Path(Replidec.__file__).resolve()
|
|
100
|
+
print(f"Testing RepliDec {Replidec.__version__} from {package_path}")
|
|
101
|
+
assert workspace not in package_path.parents, (
|
|
102
|
+
"Candidate import resolved to the checkout instead of the installed package"
|
|
103
|
+
)
|
|
104
|
+
assert Replidec.__version__ == expected.group(1), (
|
|
105
|
+
"Candidate code did not replace the published Bioconda package"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
with Path(os.environ["GITHUB_OUTPUT"]).open("a", encoding="utf-8") as output:
|
|
109
|
+
output.write(f"package-dir={package_path.parent}\n")
|
|
110
|
+
output.write(f"database-version={DATABASE_MANIFEST['version']}\n")
|
|
111
|
+
output.write(f"database-url={DATABASE_MANIFEST['url']}\n")
|
|
112
|
+
PY
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
Replidec --version
|
|
116
|
+
replidec --version
|
|
117
|
+
|
|
118
|
+
- name: Restore the reference database
|
|
119
|
+
uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0
|
|
120
|
+
with:
|
|
121
|
+
path: ${{ steps.candidate.outputs.package-dir }}/db
|
|
122
|
+
key: replidec-db-site-packages-${{ runner.os }}-v${{ steps.candidate.outputs.database-version }}
|
|
123
|
+
|
|
124
|
+
- name: Download and verify the reference database on a cache miss
|
|
125
|
+
env:
|
|
126
|
+
DATABASE_DIR: ${{ steps.candidate.outputs.package-dir }}/db
|
|
127
|
+
DATABASE_URL: ${{ steps.candidate.outputs.database-url }}
|
|
128
|
+
run: |
|
|
129
|
+
set -euo pipefail
|
|
130
|
+
|
|
131
|
+
if [[ -f "${DATABASE_DIR}/md5sum.list" ]] && (
|
|
132
|
+
cd "${DATABASE_DIR}" && md5sum --check --quiet md5sum.list
|
|
133
|
+
); then
|
|
134
|
+
echo "Using the cached reference database."
|
|
135
|
+
else
|
|
136
|
+
rm -rf "${DATABASE_DIR}"
|
|
137
|
+
archive="${RUNNER_TEMP}/replidec-database.tar.gz"
|
|
138
|
+
curl --fail --location \
|
|
139
|
+
--retry 5 \
|
|
140
|
+
--retry-delay 10 \
|
|
141
|
+
--retry-all-errors \
|
|
142
|
+
--silent \
|
|
143
|
+
--show-error \
|
|
144
|
+
--output "${archive}" \
|
|
145
|
+
"${DATABASE_URL}"
|
|
146
|
+
tar -xzf "${archive}" -C "$(dirname "${DATABASE_DIR}")"
|
|
147
|
+
(
|
|
148
|
+
cd "${DATABASE_DIR}"
|
|
149
|
+
md5sum --check --quiet md5sum.list
|
|
150
|
+
)
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
- name: Run release helper tests
|
|
154
|
+
run: python -m unittest discover -s test -p 'test_*.py' -v
|
|
155
|
+
|
|
156
|
+
- name: Run end-to-end tests
|
|
157
|
+
env:
|
|
158
|
+
REPLIDEC_TEST_OUTPUT_DIR: ${{ runner.temp }}/replidec-test-results
|
|
159
|
+
run: bash test/example.sh
|
|
160
|
+
|
|
161
|
+
- name: Upload test summaries and external-tool logs
|
|
162
|
+
if: always()
|
|
163
|
+
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
|
|
164
|
+
with:
|
|
165
|
+
name: replidec-test-results-${{ github.run_id }}
|
|
166
|
+
path: |
|
|
167
|
+
${{ runner.temp }}/replidec-test-results/**/prediction_summary.tsv
|
|
168
|
+
${{ runner.temp }}/replidec-test-results/**/external_tools.log
|
|
169
|
+
if-no-files-found: warn
|
|
170
|
+
retention-days: 14
|