diff --git a/README.md b/README.md index 42e93e7..4cb98f4 100644 --- a/README.md +++ b/README.md @@ -29,16 +29,10 @@ As of mid 2023 there are around ~11k genomes and the full GenBank file is ~150Mb ### `ingest/vendored` -This repository uses [`git subrepo`](https://github.com/ingydotnet/git-subrepo) to manage copies of ingest scripts in `ingest/vendored`, from [nextstrain/ingest](https://github.com/nextstrain/ingest). To pull new changes from the central ingest repository, run: +This repository uses [`git subrepo`](https://github.com/ingydotnet/git-subrepo) to manage copies of ingest scripts in [`ingest/vendored`](./ingest/vendored), from [nextstrain/ingest](https://github.com/nextstrain/ingest). To pull new changes from the central ingest repository, run: -```sh -git subrepo pull ingest/vendored -``` - -Changes should not be pushed using `git subrepo push`. - -1. For pathogen-specific changes, make them in this repository via a pull request. -2. For pathogen-agnostic changes, make them on [nextstrain/ingest](https://github.com/nextstrain/ingest) via pull request there, then use `git subrepo pull` to add those changes to this repository. +See [ingest/vendored/README.md](./ingest/vendored/README.md#vendoring) for instructions on how to update +the vendored scripts. ## Phylo diff --git a/ingest/vendored/.cramrc b/ingest/vendored/.cramrc new file mode 100644 index 0000000..153d20f --- /dev/null +++ b/ingest/vendored/.cramrc @@ -0,0 +1,3 @@ +[cram] +shell = /bin/bash +indent = 2 diff --git a/ingest/vendored/.github/workflows/ci.yaml b/ingest/vendored/.github/workflows/ci.yaml index dcb3b89..c6a218a 100644 --- a/ingest/vendored/.github/workflows/ci.yaml +++ b/ingest/vendored/.github/workflows/ci.yaml @@ -1,9 +1,11 @@ name: CI on: - - push - - pull_request - - workflow_dispatch + push: + branches: + - main + pull_request: + workflow_dispatch: jobs: shellcheck: @@ -11,3 +13,11 @@ jobs: steps: - uses: actions/checkout@v3 - uses: nextstrain/.github/actions/shellcheck@master + + cram: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + - run: pip install cram + - run: cram tests/ \ No newline at end of file diff --git a/ingest/vendored/.gitrepo b/ingest/vendored/.gitrepo index 8e42812..de1413c 100644 --- a/ingest/vendored/.gitrepo +++ b/ingest/vendored/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/nextstrain/ingest branch = main - commit = d141c04ac38796cd26366207f43454f75b3d638b - parent = 1f38f623d493bbafc25a4ab60226a4bd59ef8f6d + commit = 7617c39fae05e5882c5e6c065c5b47d500c998af + parent = b0ee1497a4d1f471ec87529fd7913fb96fbdf032 method = merge cmdver = 0.4.6 diff --git a/ingest/vendored/README.md b/ingest/vendored/README.md index a392c3a..fa91891 100644 --- a/ingest/vendored/README.md +++ b/ingest/vendored/README.md @@ -25,6 +25,31 @@ Any future updates of ingest scripts can be pulled in with: git subrepo pull ingest/vendored ``` +If you run into merge conflicts and would like to pull in a fresh copy of the +latest ingest scripts, pull with the `--force` flag: + +``` +git subrepo pull ingest/vendored --force +``` + +> **Warning** +> Beware of rebasing/dropping the parent commit of a `git subrepo` update + +`git subrepo` relies on metadata in the `ingest/vendored/.gitrepo` file, +which includes the hash for the parent commit in the pathogen repos. +If this hash no longer exists in the commit history, there will be errors when +running future `git subrepo pull` commands. + +If you run into an error similar to the following: +``` +$ git subrepo pull ingest/vendored +git-subrepo: Command failed: 'git branch subrepo/ingest/vendored '. +fatal: not a valid object name: '' +``` +Check the parent commit hash in the `ingest/vendored/.gitrepo` file and make +sure the commit exists in the commit history. Update to the appropriate parent +commit hash if needed. + ## History Much of this tooling originated in @@ -72,7 +97,9 @@ Scripts for supporting ingest workflow automation that don’t really belong in NCBI interaction scripts that are useful for fetching public metadata and sequences. - [fetch-from-ncbi-entrez](fetch-from-ncbi-entrez) - Fetch metadata and nucleotide sequences from [NCBI Entrez](https://www.ncbi.nlm.nih.gov/books/NBK25501/) and output to a GenBank file. - Useful for pathogens with metadata and annotations in custom fields that are not part of the standard [NCBI Virus](https://www.ncbi.nlm.nih.gov/labs/virus/vssi/) or [NCBI Datasets](https://www.ncbi.nlm.nih.gov/datasets/) outputs. + Useful for pathogens with metadata and annotations in custom fields that are not part of the standard [NCBI Datasets](https://www.ncbi.nlm.nih.gov/datasets/) outputs. + +Historically, some pathogen repos used the undocumented NCBI Virus API through [fetch-from-ncbi-virus](https://github.com/nextstrain/ingest/blob/c97df238518171c2b1574bec0349a55855d1e7a7/fetch-from-ncbi-virus) to fetch data. However we've opted to drop the NCBI Virus scripts due to https://github.com/nextstrain/ingest/issues/18. Potential Nextstrain CLI scripts @@ -94,3 +121,17 @@ Potential augur curate scripts - [transform-authors](transform-authors) - Abbreviates full author lists to ' et al.' - [transform-field-names](transform-field-names) - Rename fields of NDJSON records - [transform-genbank-location](transform-genbank-location) - Parses `location` field with the expected pattern `"[:][, ]"` based on [GenBank's country field](https://www.ncbi.nlm.nih.gov/genbank/collab/country/) +- [transform-strain-names](transform-strain-names) - Ordered search for strain names across several fields. + +## Software requirements + +Some scripts may require Bash ≥4. If you are running these scripts on macOS, the builtin Bash (`/bin/bash`) does not meet this requirement. You can install [Homebrew's Bash](https://formulae.brew.sh/formula/bash) which is more up to date. + +## Testing + +Most scripts are untested within this repo, relying on "testing in production". That is the only practical testing option for some scripts such as the ones interacting with S3 and Slack. + +For more locally testable scripts, Cram-style functional tests live in `tests` and are run as part of CI. To run these locally, + +1. Download Cram: `pip install cram` +2. Run the tests: `cram tests/` diff --git a/ingest/vendored/cloudfront-invalidate b/ingest/vendored/cloudfront-invalidate index dec4852..dbea398 100755 --- a/ingest/vendored/cloudfront-invalidate +++ b/ingest/vendored/cloudfront-invalidate @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Originally from @tsibley's gist: https://gist.github.com/tsibley/a66262d341dedbea39b02f27e2837ea8 set -euo pipefail diff --git a/ingest/vendored/download-from-s3 b/ingest/vendored/download-from-s3 index 44f7ff3..4981186 100755 --- a/ingest/vendored/download-from-s3 +++ b/ingest/vendored/download-from-s3 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail bin="$(dirname "$0")" diff --git a/ingest/vendored/notify-on-diff b/ingest/vendored/notify-on-diff index c304d6b..ddbe7da 100755 --- a/ingest/vendored/notify-on-diff +++ b/ingest/vendored/notify-on-diff @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail diff --git a/ingest/vendored/notify-on-job-fail b/ingest/vendored/notify-on-job-fail index 02cb6ba..7dd2409 100755 --- a/ingest/vendored/notify-on-job-fail +++ b/ingest/vendored/notify-on-job-fail @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail : "${SLACK_TOKEN:?The SLACK_TOKEN environment variable is required.}" diff --git a/ingest/vendored/notify-on-job-start b/ingest/vendored/notify-on-job-start index 3e44bb0..1c8ce7d 100755 --- a/ingest/vendored/notify-on-job-start +++ b/ingest/vendored/notify-on-job-start @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail : "${SLACK_TOKEN:?The SLACK_TOKEN environment variable is required.}" diff --git a/ingest/vendored/notify-on-record-change b/ingest/vendored/notify-on-record-change index c0bf8f7..f424252 100755 --- a/ingest/vendored/notify-on-record-change +++ b/ingest/vendored/notify-on-record-change @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail : "${SLACK_TOKEN:?The SLACK_TOKEN environment variable is required.}" diff --git a/ingest/vendored/notify-slack b/ingest/vendored/notify-slack index db98bfb..a343435 100755 --- a/ingest/vendored/notify-slack +++ b/ingest/vendored/notify-slack @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail : "${SLACK_TOKEN:?The SLACK_TOKEN environment variable is required.}" diff --git a/ingest/vendored/s3-object-exists b/ingest/vendored/s3-object-exists index faac421..679c20a 100755 --- a/ingest/vendored/s3-object-exists +++ b/ingest/vendored/s3-object-exists @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail url="${1#s3://}" diff --git a/ingest/vendored/tests/transform-strain-names/transform-strain-names.t b/ingest/vendored/tests/transform-strain-names/transform-strain-names.t new file mode 100644 index 0000000..1c05df7 --- /dev/null +++ b/ingest/vendored/tests/transform-strain-names/transform-strain-names.t @@ -0,0 +1,17 @@ +Look for strain name in "strain" or a list of backup fields. + +If strain entry exists, do not do anything. + + $ echo '{"strain": "i/am/a/strain", "strain_s": "other"}' \ + > | $TESTDIR/../../transform-strain-names \ + > --strain-regex '^.+$' \ + > --backup-fields strain_s accession + {"strain":"i/am/a/strain","strain_s":"other"} + +If strain entry does not exists, search the backup fields + + $ echo '{"strain_s": "other"}' \ + > | $TESTDIR/../../transform-strain-names \ + > --strain-regex '^.+$' \ + > --backup-fields accession strain_s + {"strain_s":"other","strain":"other"} \ No newline at end of file diff --git a/ingest/vendored/transform-strain-names b/ingest/vendored/transform-strain-names new file mode 100755 index 0000000..d86c0e4 --- /dev/null +++ b/ingest/vendored/transform-strain-names @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" +Verifies strain name pattern in the 'strain' field of the NDJSON record from +stdin. Adds a 'strain' field to the record if it does not already exist. + +Outputs the modified records to stdout. +""" +import argparse +import json +import re +from sys import stderr, stdin, stdout + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument("--strain-regex", default="^.+$", + help="Regex pattern for strain names. " + + "Strain names that do not match the pattern will be dropped.") + parser.add_argument("--backup-fields", nargs="*", + help="List of backup fields to use as strain name if the value in 'strain' " + + "does not match the strain regex pattern. " + + "If multiple fields are provided, will use the first field that has a non-empty string.") + + args = parser.parse_args() + + strain_name_pattern = re.compile(args.strain_regex) + + for index, record in enumerate(stdin): + record = json.loads(record) + + # Verify strain name matches the strain regex pattern + if strain_name_pattern.match(record.get('strain', '')) is None: + # Default to empty string if not matching pattern + record['strain'] = '' + # Use non-empty value of backup fields if provided + if args.backup_fields: + for field in args.backup_fields: + if record.get(field): + record['strain'] = str(record[field]) + break + + if record['strain'] == '': + print(f"WARNING: Record number {index} has an empty string as the strain name.", file=stderr) + + + json.dump(record, stdout, allow_nan=False, indent=None, separators=',:') + print() diff --git a/ingest/vendored/trigger b/ingest/vendored/trigger index 11d1b63..586f9cc 100755 --- a/ingest/vendored/trigger +++ b/ingest/vendored/trigger @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail : "${PAT_GITHUB_DISPATCH:=}" diff --git a/ingest/vendored/trigger-on-new-data b/ingest/vendored/trigger-on-new-data index ef71d88..470d2f4 100755 --- a/ingest/vendored/trigger-on-new-data +++ b/ingest/vendored/trigger-on-new-data @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail : "${PAT_GITHUB_DISPATCH:?The PAT_GITHUB_DISPATCH environment variable is required.}" diff --git a/ingest/vendored/upload-to-s3 b/ingest/vendored/upload-to-s3 index 31cd49b..36d171c 100755 --- a/ingest/vendored/upload-to-s3 +++ b/ingest/vendored/upload-to-s3 @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -euo pipefail bin="$(dirname "$0")"