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.
Files changed (101) hide show
  1. replidec-0.3.6/.conda/meta.yaml +42 -0
  2. replidec-0.3.6/.gitattributes +4 -0
  3. replidec-0.3.6/.github/CODEOWNERS +2 -0
  4. replidec-0.3.6/.github/ISSUE_TEMPLATE.md +15 -0
  5. replidec-0.3.6/.github/pull_request_template.md +50 -0
  6. replidec-0.3.6/.github/workflows/release.yml +386 -0
  7. replidec-0.3.6/.github/workflows/test.yml +170 -0
  8. replidec-0.3.6/.gitignore +8 -0
  9. replidec-0.3.6/.pre-commit-config.yaml +11 -0
  10. replidec-0.3.6/AGENTS.md +29 -0
  11. replidec-0.3.6/CONTRIBUTING.md +92 -0
  12. replidec-0.3.6/Dockerfile +19 -0
  13. {replidec-0.3.4 → replidec-0.3.6}/MANIFEST.in +2 -1
  14. replidec-0.3.6/PKG-INFO +242 -0
  15. replidec-0.3.6/README.md +223 -0
  16. replidec-0.3.6/README.rst +223 -0
  17. replidec-0.3.6/README.rst2 +25 -0
  18. replidec-0.3.6/RELEASING.md +65 -0
  19. replidec-0.3.6/Replidec/Replidec.py +346 -0
  20. replidec-0.3.6/Replidec/Replidec_cmdline.py +118 -0
  21. replidec-0.3.6/Replidec/Replidec_multi.py +287 -0
  22. {replidec-0.3.4 → replidec-0.3.6}/Replidec/__init__.py +2 -6
  23. replidec-0.3.6/Replidec/utility.py +36 -0
  24. replidec-0.3.6/Replidec.egg-info/PKG-INFO +242 -0
  25. {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/SOURCES.txt +22 -1
  26. {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/entry_points.txt +1 -0
  27. replidec-0.3.6/code_review.md +65 -0
  28. replidec-0.3.6/replidec_banner.jpg +0 -0
  29. replidec-0.3.6/requirements-dev.txt +2 -0
  30. replidec-0.3.6/requirements.txt +10 -0
  31. replidec-0.3.6/scripts/check_release_version.py +54 -0
  32. replidec-0.3.6/scripts/update_bioconda_recipe.py +141 -0
  33. replidec-0.3.6/setup.cfg +16 -0
  34. replidec-0.3.6/setup.py +53 -0
  35. replidec-0.3.6/test/example/example.small.list +4 -0
  36. replidec-0.3.6/test/example/genome_test.small.index +4 -0
  37. replidec-0.3.6/test/example.sh +65 -0
  38. replidec-0.3.6/test/test_release_tools.py +121 -0
  39. replidec-0.3.4/PKG-INFO +0 -190
  40. replidec-0.3.4/README.rst +0 -158
  41. replidec-0.3.4/Replidec/Replidec.py +0 -573
  42. replidec-0.3.4/Replidec/Replidec_cmdline.py +0 -96
  43. replidec-0.3.4/Replidec/Replidec_multi.py +0 -201
  44. replidec-0.3.4/Replidec/cli.py +0 -82
  45. replidec-0.3.4/Replidec/utility.py +0 -28
  46. replidec-0.3.4/Replidec.egg-info/PKG-INFO +0 -190
  47. replidec-0.3.4/setup.cfg +0 -23
  48. replidec-0.3.4/setup.py +0 -36
  49. replidec-0.3.4/test/example/example.small.list +0 -10
  50. replidec-0.3.4/test/example/genome_test.small.index +0 -10
  51. replidec-0.3.4/test/example.sh +0 -7
  52. {replidec-0.3.4 → replidec-0.3.6}/LICENSE +0 -0
  53. {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/dependency_links.txt +0 -0
  54. {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/requires.txt +0 -0
  55. {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/top_level.txt +0 -0
  56. {replidec-0.3.4 → replidec-0.3.6}/Replidec.egg-info/zip-safe +0 -0
  57. {replidec-0.3.4 → replidec-0.3.6}/test/example/example.list +0 -0
  58. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/generate.sh +0 -0
  59. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaa +0 -0
  60. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaab +0 -0
  61. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaac +0 -0
  62. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaad +0 -0
  63. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaae +0 -0
  64. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaf +0 -0
  65. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaag +0 -0
  66. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaah +0 -0
  67. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaai +0 -0
  68. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaj +0 -0
  69. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaak +0 -0
  70. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaal +0 -0
  71. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaam +0 -0
  72. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaan +0 -0
  73. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaao +0 -0
  74. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaap +0 -0
  75. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test/genome.test.fnaaq +0 -0
  76. {replidec-0.3.4 → replidec-0.3.6}/test/example/genome_test.index +0 -0
  77. {replidec-0.3.4 → replidec-0.3.6}/test/example/mock_data_single_lifestyleBC.py +0 -0
  78. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.1.faa +0 -0
  79. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.10.faa +0 -0
  80. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.11.faa +0 -0
  81. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.12.faa +0 -0
  82. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.13.faa +0 -0
  83. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.14.faa +0 -0
  84. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.15.faa +0 -0
  85. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.16.faa +0 -0
  86. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.17.faa +0 -0
  87. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.18.faa +0 -0
  88. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.19.faa +0 -0
  89. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.2.faa +0 -0
  90. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.20.faa +0 -0
  91. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.21.faa +0 -0
  92. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.22.faa +0 -0
  93. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.3.faa +0 -0
  94. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.4.faa +0 -0
  95. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.5.faa +0 -0
  96. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.6.faa +0 -0
  97. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.7.faa +0 -0
  98. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.8.faa +0 -0
  99. {replidec-0.3.4 → replidec-0.3.6}/test/example/simulate_art_sample1.9.faa +0 -0
  100. {replidec-0.3.4 → replidec-0.3.6}/test/example/test.contig.small.fa +0 -0
  101. {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,2 @@
1
+ # Every change entering main requires final review from the repository owner.
2
+ * @pengSherryYel
@@ -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
@@ -0,0 +1,8 @@
1
+ build/
2
+ Replidec.egg-info/
3
+ dist/
4
+ __pycache__/
5
+ *.py[cod]
6
+ sectest/
7
+ .idea
8
+ Replidec/db/
@@ -0,0 +1,11 @@
1
+ # One-time setup:
2
+ # python -m pip install -r requirements-dev.txt
3
+ # pre-commit install --hook-type pre-push
4
+ repos:
5
+ - repo: https://github.com/pycqa/flake8
6
+ rev: 7.3.0
7
+ hooks:
8
+ - id: flake8
9
+ name: Flake8
10
+ stages:
11
+ - pre-push