This guide is for internal Snyk contributors with write access to this repository.
To install the required development dependencies in homebrew based environments, execute the following script from the root directory. The only additional prerequisite is having homebrew installed.
./scripts/install-dev-dependencies.sh
Clone this repository with git.
git clone [email protected]/snyk/cli.git
cd snyk
You will now be on our main
branch. You should never commit to this branch, but you should keep it up-to-date to ensure you have the latest changes.
git fetch
git pull --ff-only
If you encounter vague errors without a clear solution at any point, try starting over by cloning a new copy or cleaning the project.
make clean
To build the project, run the following command in the root of the repository.
make build
# or
make build-debug
Run the build binary like this.
./binary-releases/snyk-macos --version
-
Build the cli using
make build-debug
-
Save the
Installing
path from the build output -
Open your
.vscode/launch.json
file and add the following underconfigurations
{
"name": "Attach to Go Process",
"type": "go",
"request": "attach",
"mode": "local",
"remotePath": "<your Installing path>"
}
-
Add your break points
-
Run the cli from your build path, you will see a prompt to attach a Debugger
-
Run "Attach to Go Process" from under your debug tab
You can run tests using standard Jest commands. See: Jest CLI docs.
npx jest --runInBand <path>
For closed box tests (like User Journey tests, acceptance tests, ...) you will have to specify the binary under test by setting the environment variable TEST_SNYK_COMMAND.
TEST_SNYK_COMMAND=./binary-releases/snyk-macos npx jest --runInBand <path>
If you are working on a specific project, you can filter by project.
npx jest --runInBand --selectProjects @snyk/protect <path>
Debugger configuration is available for VS Code. Open "Run and Debug" and choose "Jest Current File".
Typically, you should not run the full test suite locally. Snyk CLI includes a variety of features which require various tools and configuration to be installed. Our PR pipeline will take care of most of that. Locally, you should focus on the tests related to your changes.
All tests end in .spec.ts
and use Jest. There are two types of tests:
./test/jest/unit
- Unit tests targeting source code (./src
)../test/jest/acceptance
- Acceptance tests targeting distributables (./dist
).
Each test must start from a clean slate to avoid pollution. Do not share state between tests and always perform any setup within the test itself or in specific before and after hooks.
To avoid hard wiring tests to your specific implementation, try writing the test first.
Unit tests enforce the correctness of our source code. Ensure the path to the test mirrors the path to the source.
Unit tests must be fast. They should not test services outside the code itself. Services include filesystems, processes and networks.
Avoid using mocks as these can go out of sync and be difficult to maintain; prefer interfaces instead.
If you are mostly testing functions calling other functions, consider writing an acceptance test instead. Otherwise, your tests will likely mirror the implementation and rely heavily on mocks; making future changes difficult.
Acceptance tests enforce the correctness of our distribution and are written from the perspective of an user.
Snyk CLI's acceptance tests execute a specific command line as a standalone process, then assert on stdout
, stdin
and the exit code. As an example, see: oauth-token.spec.ts
.
Your tests should never call remote endpoints. Otherwise, our release pipelines will require those services to be available. To avoid this, we can assume external services are kept compatible. If any of these services cause issues, we can rely on production monitoring to alert us.
Use fake-server to mock any Snyk API calls. If you are using other endpoints, mock those too in a similar way.
Place fixtures in ./test/fixtures
. Keep them minimal to reduce maintenance. Use createProject
to use your fixtures in isolated working directories for your tests.
Before running the tests locally you will need to:
- Set the
TEST_SNYK_TOKEN
environment variable with a valid API token. - Run
make build
to ensure you have binary - Set
TEST_SNYK_COMMAND
to the path of the built binary for your environment, for example:./binary-releases/snyk-macos
You can run acceptance tests with:
npm run test:acceptance -- --selectProjects coreCli
Smoke tests typically don't run on branches unless the branch is specifically prefixed with smoke/
. They usually run on an hourly basis against the latest published version of the CLI.
If you merge a PR that changes smoke tests, remember that the tests will fail until your changes are deployed.
See the smoke tests readme for more info
For current ownership assignments, see: CODEOWNERS.
To avoid mixing ownership into a single file, move team-specific logic into separate files. To reduce blockers and save time, design with ownership in mind.
When adding and upgrading dependencies, ensure the package-lock.json
results in minimal updates. To do this you can:
npm ci
npm install <your dependency>
It's best to avoid adding external dependencies. All dependency changes are reviewed by Hammerhead.
When implementing a feature that is at first in beta state, consider requiring the --experimental
flag to be set. This increases visibility in the state of the feature being used.
To ensure your changes follow formatting guidelines, you can run the linter.
npm run lint
To fix various issues automatically you can install ESLint and Prettier plugins for your IDE or run the following:
npm run format
You will need to fix any remaining issues manually.
When making changes, ensure documentation is updated accordingly.
User-facing documentation is available on GitBook.
snyk help
output must also be edited on GitBook. Changes will automatically be pulled into Snyk CLI as pull requests.
Create a new branch before making any changes. Make sure to give it a descriptive name so that you can find it later.
git checkout -b type/topic
For example:
git checkout -b docs/contributing
You can use these patterns in your branch name to enable additional checks.
Pattern | Examples | Description |
---|---|---|
chore/* , *test* |
chore/change , test/change , feat/change+test |
Build and test all artifacts, excluding CLIv2. Same as a release pipeline without the release step. |
smoke/* |
smoke/change |
Run smoke tests against the latest release. |
*e2e* |
chore/feature1_e2e |
Run parts of the deployment pipeline to cover end to end tests already on the current branch |
default | fix/a-bug |
Build and test your changes. |
For more information, see: Pull request checks.
Each commit must provide some benefit on its own without breaking the release pipeline.
For larger changes, break down each step into multiple commits so that it's easy to review in pull requests and git history.
Commits must follow Conventional Commits structure:
type: summary of your changes
reasoning behind your changes
For example:
docs: update contributing guide
We often get questions on how to contribute to this repo. What versions to use, what the workflow is, and so on. This change updates our CONTRIBUTING guide to answer those types of questions.
The commit type is used to summarize intent and to automate various steps.
Type | Description |
---|---|
feat |
A new user-facing feature. |
fix |
A bug fix for an existing feature. |
chore |
Build, workflow and pipeline changes. |
test |
Changes to tests for existing features. |
refactor |
Changes which do not affect existing features. |
docs |
Changes to documentation for existing features. |
revert |
Reverting a previous commit. |
When writing your commit message, keep in mind that it will be used to build our user-facing release notes. To ensure everyone benefits from your changes, please write messages that are clear and concise, even for those unfamiliar with the code itself.
Focus on the what rather than the how. Instead of "Upgraded external-dependency" explain the impact this has on users: "Improved search accuracy to deliver more relevant results". This way, users can easily see the value of upgrading to the latest release.
Your changes must be backwards compatible and cannot break existing user pipelines.
Don't use BREAKING CHANGE
or exclamation mark !
from the Conventional Commits.
Once you have committed your changes, review them locally, then push them to GitHub.
git push
Do not hold onto your changes for too long. Commit and push frequently and create a pull request as soon as possible for backup and visibility.
You can now create a Draft PR on GitHub. Make sure to switch the big green button to a "Draft Pull Request". Draft PRs allow you to ensure your PR checks pass before asking for a review.
To keep things simple, try to use the most important commit as the PR's title. Provide some context and summarize the changes in your body.
If your PR becomes too large, consider breaking it up into multiple PRs so that it's easier to explain, review, and integrate.
Your PR checks will run every time you push changes to your branch.
Name | Failure action |
---|---|
test_and_release |
See: Test pipeline. |
Danger |
Check the comment created on your PR. |
license/cla |
Visit CLA Assistant to sign or re-run it. |
Everything else. | Ask Hammerhead. |
The test pipeline is on CircleCI. This is where your changes are built and tested.
If any checks fail, fix them and force push your changes again. Make sure to review and tidy up your branch so that it remains easy to follow.
Some tests may "flake", meaning they failed due to some external factor. While we try to fix these tests immediately, that's not always possible. You can use CircleCI's "Re-run from Failed" option to re-run only that job without needing to re-run the entire pipeline.
Once your checks have passed, you can publish your Draft PR. Codeowners will be automatically assigned. Ask each codeowner for a review using relevant channels on Slack. Iterate on feedback. All pull requests must undergo a thorough review process before being merged. This includes:
- Code review
- Testing
- Documentation review (if applicable)
- Any necessary feedback or revisions
Pull request reviews of functionality developed in other teams only review the given documentation and test reports. Manual testing will not be performed by the reviewing team and is the responsibility of the author of the PR.
For Node projects: Ensure changes in package.json are correctly reflected in package-lock.json.
When adding a new package as a dependency, make sure that the change is absolutely necessary. We aim to minimize new dependencies when possible.
Documentation PRs in GitBook are reviewed by Snyk's content team. They will also advise on the best phrasing and structuring if needed.
Once a pull request has been reviewed and all necessary revisions have been made, it is approved for merging into the main codebase. The merging of the code PR is performed by the code owners, while the merging of the documentation PR is done by our content writers.
Merges will create a release pipeline which will build and test your changes against a range of target platforms.
Once all tests have passed, you will be given the choice to publish a new release containing your changes.
All releases are minor version bumps. For the latest releases, see: Releases.
If you do not want to publish your changes immediately, you can "Cancel Workflow".
If your release pipeline fails at any step, notify Hammerhead.
You may see some "Docker Hub" checks on your merge commit fail. This is normal and safe to ignore.
After the release-npm
job successfully completes, an automated process generates the Docker images for Snyk CLI. These images are then published to DockerHub under the repository snyk/snyk
.
If you have made changes to the go-application-framework
, you can run python3 scripts/upgrade-go-application-framework.py
. This will;
- Fetch the most recent commit from main of the framework
- Go get that version of the framework
You can then raise a pr with the relevant changes.
When upgrading golang, you will need to update the Dockerfile under .circleci, run the Create Build Image job on github, and update the docker executor that use the snyklabs/cli-build
image in the .circleci/config.yml file, to use the new image.
Questions? Ask Hammerhead 🔨