{"payload":{"allShortcutsEnabled":false,"fileTree":{"":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":".null","path":".null","contentType":"directory"},{"name":"build","path":"build","contentType":"directory"},{"name":"cli","path":"cli","contentType":"directory"},{"name":"docs","path":"docs","contentType":"directory"},{"name":"examples","path":"examples","contentType":"directory"},{"name":"narratives","path":"narratives","contentType":"directory"},{"name":"scripts","path":"scripts","contentType":"directory"},{"name":"src","path":"src","contentType":"directory"},{"name":"test","path":"test","contentType":"directory"},{"name":".editorconfig","path":".editorconfig","contentType":"file"},{"name":".eslintignore","path":".eslintignore","contentType":"file"},{"name":".eslintrc.yaml","path":".eslintrc.yaml","contentType":"file"},{"name":".gitattributes","path":".gitattributes","contentType":"file"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":".npmignore","path":".npmignore","contentType":"file"},{"name":"CHANGELOG.md","path":"CHANGELOG.md","contentType":"file"},{"name":"DEV_DOCS.md","path":"DEV_DOCS.md","contentType":"file"},{"name":"LICENSE.txt","path":"LICENSE.txt","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"app.json","path":"app.json","contentType":"file"},{"name":"auspice.js","path":"auspice.js","contentType":"file"},{"name":"babel.config.js","path":"babel.config.js","contentType":"file"},{"name":"bundlesize.config.json","path":"bundlesize.config.json","contentType":"file"},{"name":"favicon.png","path":"favicon.png","contentType":"file"},{"name":"index.js","path":"index.js","contentType":"file"},{"name":"jest-puppeteer.config.js","path":"jest-puppeteer.config.js","contentType":"file"},{"name":"package-lock.json","path":"package-lock.json","contentType":"file"},{"name":"package.json","path":"package.json","contentType":"file"},{"name":"puppeteer.config.js","path":"puppeteer.config.js","contentType":"file"},{"name":"puppeteer.setup.js","path":"puppeteer.setup.js","contentType":"file"},{"name":"readthedocs.yml","path":"readthedocs.yml","contentType":"file"},{"name":"releaseNewVersion.sh","path":"releaseNewVersion.sh","contentType":"file"},{"name":"tsconfig.json","path":"tsconfig.json","contentType":"file"},{"name":"webpack.config.js","path":"webpack.config.js","contentType":"file"}],"totalCount":35}},"fileTreeProcessingTime":5.436467,"foldersToFetch":[],"repo":{"id":56881532,"defaultBranch":"master","name":"auspice","ownerLogin":"nextstrain","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2016-04-22T19:54:18.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/22159334?v=4","public":true,"private":false,"isOrgOwned":true},"symbolsExpanded":false,"treeExpanded":true,"refInfo":{"name":"master","listCacheKey":"v0:1710589204.0","canEdit":false,"refType":"branch","currentOid":"cff84b3cbf13212a91c537a0b63e824682b7ebc0"},"path":"DEV_DOCS.md","currentUser":null,"blob":{"rawLines":null,"stylingDirectives":null,"colorizedLines":null,"csv":null,"csvError":null,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/nextstrain/auspice/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"DEV_DOCS.md","displayUrl":"https://github.com/nextstrain/auspice/blob/master/DEV_DOCS.md?raw=true","headerInfo":{"blobSize":"10.6 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"3601239","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fnextstrain%2Fauspice%2Fblob%2Fmaster%2FDEV_DOCS.md","isCSV":false,"isRichtext":true,"toc":[{"level":1,"text":"Contributing to Auspice development","anchor":"contributing-to-auspice-development","htmlText":"Contributing to Auspice development"},{"level":2,"text":"Developer Installation","anchor":"developer-installation","htmlText":"Developer Installation"},{"level":2,"text":"Contributing code","anchor":"contributing-code","htmlText":"Contributing code"},{"level":3,"text":"Make sure tests are passing","anchor":"make-sure-tests-are-passing","htmlText":"Make sure tests are passing"},{"level":4,"text":"For unit tests","anchor":"for-unit-tests","htmlText":"For unit tests"},{"level":4,"text":"For linting","anchor":"for-linting","htmlText":"For linting"},{"level":4,"text":"For integration tests","anchor":"for-integration-tests","htmlText":"For integration tests"},{"level":4,"text":"For smoke tests","anchor":"for-smoke-tests","htmlText":"For smoke tests"},{"level":4,"text":"Test Tips","anchor":"test-tips","htmlText":"Test Tips"},{"level":4,"text":"Manual testing","anchor":"manual-testing","htmlText":"Manual testing"},{"level":4,"text":"Test on downstream repositories","anchor":"test-on-downstream-repositories","htmlText":"Test on downstream repositories"},{"level":2,"text":"git-lfs","anchor":"git-lfs","htmlText":"git-lfs"},{"level":2,"text":"Typescript","anchor":"typescript","htmlText":"Typescript"},{"level":2,"text":"Contributing to Documentation","anchor":"contributing-to-documentation","htmlText":"Contributing to Documentation"},{"level":2,"text":"Contributing to Internationalization and Localization (i18n/l18n)","anchor":"contributing-to-internationalization-and-localization-i18nl18n","htmlText":"Contributing to Internationalization and Localization (i18n/l18n)"},{"level":2,"text":"Adding a new language","anchor":"adding-a-new-language","htmlText":"Adding a new language"},{"level":2,"text":"Helper script to check what parts of a translation are out-of-date or missing","anchor":"helper-script-to-check-what-parts-of-a-translation-are-out-of-date-or-missing","htmlText":"Helper script to check what parts of a translation are out-of-date or missing"},{"level":2,"text":"Improving an existing translation","anchor":"improving-an-existing-translation","htmlText":"Improving an existing translation"},{"level":2,"text":"Releases & versioning","anchor":"releases--versioning","htmlText":"Releases & versioning"}],"lineInfo":{"truncatedLoc":"219","truncatedSloc":"138"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"issueTemplate":null,"discussionTemplate":null,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/nextstrain/auspice/blob/master/DEV_DOCS.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/nextstrain/auspice/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/nextstrain/auspice/raw/master/DEV_DOCS.md","renderImageOrRaw":false,"richText":"

Contributing to Auspice development

\n\n\n\n\n\n\n\n\n\n\n

Thank you for helping us to improve Nextstrain!

\n
\n

To get started, please see the contributing guide for useful information about how to pick an issue, submit your contributions, and so on.

\n
\n

This project strictly adheres to the Contributor Covenant Code of Conduct.

\n

Please see the project boards for currently available issues.

\n

Developer Installation

\n

This is useful for debugging, modifying the source code, or using an unpublished feature branch.

\n

You can install using your system npm or within a Conda environment to keep things isolated.

\n
# grab the GitHub auspice repo\ngit clone https://github.com/nextstrain/auspice.git\ncd auspice\n\n# install dependencies and build auspice\nnpm ci\n\n# make `auspice` available globally\nnpm install --global .
\n

Updating Auspice should only require pulling the new version from GitHub - it shouldn't require any npm commands. You will, however, have to re-build Auspice whenever the client-related code has changed, via auspice build.

\n

Contributing code

\n

Please comment on an open issue if you are working on it.\nFor changes unrelated to an open issue, please make an issue outlining what you would like to change/add.

\n

Where possible, please rebase your work onto master rather than merging changes from master into your PR.

\n

From a fork: git pull --rebase upstream master

\n

Make sure tests are passing

\n

We use the following libraries for all kinds of testing, so it'd help to read the docs to get familiar with their APIs and features:

\n
    \n
  1. Jest
  2. \n
  3. Puppeteer
  4. \n
  5. Jest-Puppeteer
  6. \n
  7. Jest-Image-Snapshot
  8. \n
\n

When you submit a pull request to the auspice repository, certain tests will need to pass before it can be merged.

\n

You will likely want to run these tests locally before submitting:

\n

First, install the dependencies with npm i, then:

\n

For unit tests

\n

Run npm test.

\n

For linting

\n

Run npm run lint. If there are issues run npm run lint:fix.

\n

For integration tests

\n

Auspice used to have integration testing using jest + puppeteer, however this was removed in PR 1672.\nIdeally this functionality will be brought back, and that PR would be a good place to start.

\n

For smoke tests

\n
    \n
  1. Fetch the datasets with npm run get-data.
  2. \n
  3. Ensure you are not currently running the site locally, then run npm run smoke-test:ci.
  4. \n
\n

Test Tips

\n
    \n
  1. \n

    Run a single describe(), it(), or test() within a file, add .only():

    \n

    E.g., describe.only(), it.only(), or test.only()

    \n
  2. \n
  3. \n

    You can run a single test file like so:

    \n

    E.g., npx jest test/dates.test.js

    \n
  4. \n
\n

Manual testing

\n

A Heroku pipeline for this repository is connected to GitHub under the nextstrain-bot user account. The Review Apps feature facilitates manual review of changes by automatically creating a test instance from the PR source branch and adding a link to it on the GitHub PR page. These apps are based on configuration in app.json.

\n

Test on downstream repositories

\n

Additionally, a GitHub Actions workflow has been set up to generate PRs in downstream repositories that reflect the new changes in Auspice. To use it:

\n
    \n
  1. Go to the workflow page.
  2. \n
  3. Select Run workflow.
  4. \n
  5. Pick the PR branch, select the downstream repositories you wish to test, and Run workflow.
  6. \n
  7. Wait for the workflow to finish running. The Auspice PR should show new reference links from the generated PRs.
  8. \n
\n

git-lfs

\n

Git Large File Storage was removed in PR 1672.\nYou may uninstall it via git lfs uninstall if needed.

\n

Typescript

\n

Auspice is in the process of moving to typescript, and currently supports both .js(x) and .ts(x) files.\nThis guide is helpful to understand the bigger picture of migrating a JS project to TS.\nTypescript is supposed to help us, so there's no problem using any types as we move code from JS to TS, however new code would ideally be typed.

\n

You can check the types via npm type-check or run npm type-check:watch; alternatively your editor should be able to show this.

\n

Our CI (GitHub action) will type-check the project.

\n

The various moving parts involved are:

\n\n

Contributing to Documentation

\n

The main Nextstrain documentation is available at docs.nextstrain.org. That documentation is built from the docs.nextstrain.org GitHub repo -- see the contributing page for docs.nextstrain.org for more details on how to contribute to that documentation.

\n

The Auspice technical reference guide is available at docs.nextstrain.org/projects/auspice. That documentation is built from the files in this repo in the ./docs folder.

\n

To preview the Auspice documentation locally,

\n
    \n
  1. \n

    Create and activate a Conda environment from docs/conda.yml. Example:

    \n
    conda env create --file docs/conda.yml\nconda activate auspice-docs
    \n
  2. \n
  3. \n

    Build the docs from a clean slate.

    \n
    make -C docs clean livehtml
    \n
  4. \n
  5. \n

    Open the preview link (http://127.0.0.1:8000) in a browser.

    \n
  6. \n
\n

Changes to documentation source files (.md and .rst files under docs/) should automatically be reflected upon page refresh.

\n

Contributing to Internationalization and Localization (i18n/l18n)

\n

If you can assist in efforts to translate the Auspice interface to more languages your assistance would be very much appreciated.\nThe currently available languages are displayed via a drop-down at the bottom of the sidebar.

\n

Adding a new language

\n
    \n
  1. Add the language to the getlanguageOptions function in this file
  2. \n
  3. If this is a new language, copy the folder (and the JSONs within it) src/locales/en and name it to match the language code for the new translation -- e.g. for Spanish this would be src/locales/es
  4. \n
  5. For each key-value in the JSONs, translate the english phrase to the new locale. (Do not modify the strings within {{...}} sections.)
  6. \n
\n

For example, a spanish translation would change the English:

\n
  \"sampled between {{from}} and {{to}}\": \"sampled between {{from}} and {{to}}\",\n  \"and comprising\": \"and comprising\",
\n

to

\n
  \"sampled between {{from}} and {{to}}\": \"aislados entre {{from}} y {{to}}\",\n  \"and comprising\": \"y compuesto de\",
\n

Helper script to check what parts of a translation are out-of-date or missing

\n

Run npm run diff-lang -- X, where X is the language you wish to check, for instance es.\nThis will display the strings which:

\n\n
\n

Running npm run diff-lang will check all available languages.

\n
\n

Improving an existing translation

\n

If a translation of a particular string is not yet available, then auspice will fall-back to the english version.

\n
    \n
  1. Find the relevant key in the (EN) JSONs in this directory
  2. \n
  3. Add the key to the JSON with the same name, but in the directory corresponding to the language you are translating into (see above for an example).
  4. \n
\n

Releases & versioning

\n
    \n
  1. Run the ./releaseNewVersion.sh script from an up-to-date master branch. It will prompt you for the version number increase, push changes to the release branch and, as long as the GitHub workflow is successful then a new version will be automatically published to npm.\n\n
  2. \n
  3. Update the version on Bioconda:\n
      \n
    1. \n

      Click to edit the Bioconda recipe. Or, consider using the Nextstrain fork to create PRs that other team members can contribute to.

      \n
    2. \n
    3. \n

      Make the following changes:

      \n
        \n
      1. \n

        Update the version number in the first line.

        \n
      2. \n
      3. \n

        Change source.sha256 to the sha256 hash of the file at source.url. You can get the value using the following command:

        \n
        curl -s https://registry.npmjs.com/auspice/latest \\\n    | jq -r \".dist.tarball\" \\\n    | xargs curl -s \\\n    | shasum -a 256 \\\n    | cut -f 1 -d \" \"
        \n
      4. \n
      \n
    4. \n
    5. \n

      Click through to create a Pull Request to the Bioconda GitHub repository.

      \n
    6. \n
    \n
  4. \n
  5. When the new version of Auspice is available on Bioconda, manually run the conda-base CI workflow on the main branch.
  6. \n
\n
","renderedFileInfo":null,"shortPath":null,"symbolsEnabled":true,"tabSize":2,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"Contributing to Auspice development","kind":"section_1","ident_start":2,"ident_end":37,"extent_start":0,"extent_end":10812,"fully_qualified_name":"Contributing to Auspice development","ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":37}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":219,"utf16_col":0}}},{"name":"Developer Installation","kind":"section_2","ident_start":1268,"ident_end":1290,"extent_start":1265,"extent_end":2033,"fully_qualified_name":"Developer Installation","ident_utf16":{"start":{"line_number":21,"utf16_col":3},"end":{"line_number":21,"utf16_col":25}},"extent_utf16":{"start":{"line_number":21,"utf16_col":0},"end":{"line_number":41,"utf16_col":0}}},{"name":"Contributing code","kind":"section_2","ident_start":2036,"ident_end":2053,"extent_start":2033,"extent_end":4765,"fully_qualified_name":"Contributing code","ident_utf16":{"start":{"line_number":41,"utf16_col":3},"end":{"line_number":41,"utf16_col":20}},"extent_utf16":{"start":{"line_number":41,"utf16_col":0},"end":{"line_number":109,"utf16_col":0}}},{"name":"Make sure tests are passing","kind":"section_3","ident_start":2385,"ident_end":2412,"extent_start":2381,"extent_end":4765,"fully_qualified_name":"Make sure tests are passing","ident_utf16":{"start":{"line_number":50,"utf16_col":4},"end":{"line_number":50,"utf16_col":31}},"extent_utf16":{"start":{"line_number":50,"utf16_col":0},"end":{"line_number":109,"utf16_col":0}}},{"name":"For unit tests","kind":"section_4","ident_start":3047,"ident_end":3061,"extent_start":3042,"extent_end":3080,"fully_qualified_name":"For unit tests","ident_utf16":{"start":{"line_number":65,"utf16_col":5},"end":{"line_number":65,"utf16_col":19}},"extent_utf16":{"start":{"line_number":65,"utf16_col":0},"end":{"line_number":69,"utf16_col":0}}},{"name":"For linting","kind":"section_4","ident_start":3085,"ident_end":3096,"extent_start":3080,"extent_end":3163,"fully_qualified_name":"For linting","ident_utf16":{"start":{"line_number":69,"utf16_col":5},"end":{"line_number":69,"utf16_col":16}},"extent_utf16":{"start":{"line_number":69,"utf16_col":0},"end":{"line_number":73,"utf16_col":0}}},{"name":"For integration tests","kind":"section_4","ident_start":3168,"ident_end":3189,"extent_start":3163,"extent_end":3438,"fully_qualified_name":"For integration tests","ident_utf16":{"start":{"line_number":73,"utf16_col":5},"end":{"line_number":73,"utf16_col":26}},"extent_utf16":{"start":{"line_number":73,"utf16_col":0},"end":{"line_number":78,"utf16_col":0}}},{"name":"For smoke tests","kind":"section_4","ident_start":3443,"ident_end":3458,"extent_start":3438,"extent_end":3605,"fully_qualified_name":"For smoke tests","ident_utf16":{"start":{"line_number":78,"utf16_col":5},"end":{"line_number":78,"utf16_col":20}},"extent_utf16":{"start":{"line_number":78,"utf16_col":0},"end":{"line_number":84,"utf16_col":0}}},{"name":"Test Tips","kind":"section_4","ident_start":3610,"ident_end":3619,"extent_start":3605,"extent_end":3853,"fully_qualified_name":"Test Tips","ident_utf16":{"start":{"line_number":84,"utf16_col":5},"end":{"line_number":84,"utf16_col":14}},"extent_utf16":{"start":{"line_number":84,"utf16_col":0},"end":{"line_number":96,"utf16_col":0}}},{"name":"Manual testing","kind":"section_4","ident_start":3858,"ident_end":3872,"extent_start":3853,"extent_end":4216,"fully_qualified_name":"Manual testing","ident_utf16":{"start":{"line_number":96,"utf16_col":5},"end":{"line_number":96,"utf16_col":19}},"extent_utf16":{"start":{"line_number":96,"utf16_col":0},"end":{"line_number":100,"utf16_col":0}}},{"name":"Test on downstream repositories","kind":"section_4","ident_start":4221,"ident_end":4252,"extent_start":4216,"extent_end":4765,"fully_qualified_name":"Test on downstream repositories","ident_utf16":{"start":{"line_number":100,"utf16_col":5},"end":{"line_number":100,"utf16_col":36}},"extent_utf16":{"start":{"line_number":100,"utf16_col":0},"end":{"line_number":109,"utf16_col":0}}},{"name":"git-lfs","kind":"section_2","ident_start":4768,"ident_end":4775,"extent_start":4765,"extent_end":4971,"fully_qualified_name":"git-lfs","ident_utf16":{"start":{"line_number":109,"utf16_col":3},"end":{"line_number":109,"utf16_col":10}},"extent_utf16":{"start":{"line_number":109,"utf16_col":0},"end":{"line_number":115,"utf16_col":0}}},{"name":"Typescript","kind":"section_2","ident_start":4974,"ident_end":4984,"extent_start":4971,"extent_end":5931,"fully_qualified_name":"Typescript","ident_utf16":{"start":{"line_number":115,"utf16_col":3},"end":{"line_number":115,"utf16_col":13}},"extent_utf16":{"start":{"line_number":115,"utf16_col":0},"end":{"line_number":131,"utf16_col":0}}},{"name":"Contributing to Documentation","kind":"section_2","ident_start":5934,"ident_end":5963,"extent_start":5931,"extent_end":7152,"fully_qualified_name":"Contributing to Documentation","ident_utf16":{"start":{"line_number":131,"utf16_col":3},"end":{"line_number":131,"utf16_col":32}},"extent_utf16":{"start":{"line_number":131,"utf16_col":0},"end":{"line_number":156,"utf16_col":0}}},{"name":"Contributing to Internationalization and Localization (i18n/l18n)","kind":"section_2","ident_start":7155,"ident_end":7220,"extent_start":7152,"extent_end":7447,"fully_qualified_name":"Contributing to Internationalization and Localization (i18n/l18n)","ident_utf16":{"start":{"line_number":156,"utf16_col":3},"end":{"line_number":156,"utf16_col":68}},"extent_utf16":{"start":{"line_number":156,"utf16_col":0},"end":{"line_number":161,"utf16_col":0}}},{"name":"Adding a new language","kind":"section_2","ident_start":7450,"ident_end":7471,"extent_start":7447,"extent_end":8310,"fully_qualified_name":"Adding a new language","ident_utf16":{"start":{"line_number":161,"utf16_col":3},"end":{"line_number":161,"utf16_col":24}},"extent_utf16":{"start":{"line_number":161,"utf16_col":0},"end":{"line_number":181,"utf16_col":0}}},{"name":"Helper script to check what parts of a translation are out-of-date or missing","kind":"section_2","ident_start":8313,"ident_end":8390,"extent_start":8310,"extent_end":8776,"fully_qualified_name":"Helper script to check what parts of a translation are out-of-date or missing","ident_utf16":{"start":{"line_number":181,"utf16_col":3},"end":{"line_number":181,"utf16_col":80}},"extent_utf16":{"start":{"line_number":181,"utf16_col":0},"end":{"line_number":192,"utf16_col":0}}},{"name":"Improving an existing translation","kind":"section_2","ident_start":8779,"ident_end":8812,"extent_start":8776,"extent_end":9214,"fully_qualified_name":"Improving an existing translation","ident_utf16":{"start":{"line_number":192,"utf16_col":3},"end":{"line_number":192,"utf16_col":36}},"extent_utf16":{"start":{"line_number":192,"utf16_col":0},"end":{"line_number":199,"utf16_col":0}}},{"name":"Releases & versioning","kind":"section_2","ident_start":9217,"ident_end":9238,"extent_start":9214,"extent_end":10812,"fully_qualified_name":"Releases & versioning","ident_utf16":{"start":{"line_number":199,"utf16_col":3},"end":{"line_number":199,"utf16_col":24}},"extent_utf16":{"start":{"line_number":199,"utf16_col":0},"end":{"line_number":219,"utf16_col":0}}}]}},"copilotInfo":null,"copilotAccessAllowed":false,"csrf_tokens":{"/nextstrain/auspice/branches":{"post":"Pc5JWmq9JB5MRWmG25E7W19H0FmHVO_4b2zCBEa_IrodPq84k6wn08enelZ6DoTM-oRkkuqHDnO1sv1JlBuoEQ"},"/repos/preferences":{"post":"lIAYT91V43lTSjtHmN_BoqUlDpxet8LGsVLtL5ISq71ZsckdmKOqFQaJ_izTDmcfEtnbS6o7G_eXAqvc-SHAJA"}}},"title":"auspice/DEV_DOCS.md at master ยท nextstrain/auspice"}