Skip to content

Latest commit

 

History

History
407 lines (301 loc) · 17.8 KB

CONTRIBUTING.md

File metadata and controls

407 lines (301 loc) · 17.8 KB

Contributing to AWS Toolkit for VS Code

Thanks for taking the time to help improve the AWS Toolkit! We greatly value feedback and contributions from the community.

Reviewing this document will maximize your success in working with the codebase and sending pull requests.

Getting Started

Find things to do

If you're looking for ideas about where to contribute, consider good first issue issues.

Setup

To develop this project, install these dependencies:

Then clone the repository and install NPM packages:

git clone [email protected]:aws/aws-toolkit-vscode.git
cd aws-toolkit-vscode
npm install

Run

You can run the extension from Visual Studio Code:

  1. Select the Run panel from the sidebar.
  2. From the dropdown at the top of the Run pane, choose Extension.
  3. Press F5 to launch a new instance of Visual Studio Code with the extension installed and the debugger attached.

Build

When you launch the extension or run tests from Visual Studio Code, it will automatically build the extension and watch for changes.

You can also use these NPM tasks (see npm run for the full list):

  • To build once:
    npm run compile
    
  • To build and watch for file changes:
    npm run watch
    
  • To build a release artifact (VSIX):
    npm run package
    
    • This uses webpack which may exhaust the default Node heap size on Linux. To fix this set --max-old-space-size:
      export NODE_OPTIONS=--max-old-space-size=8192
      
  • To build a "debug" VSIX artifact (faster and does not minify):
    npm run package -- --debug
    

Develop

Guidelines

Technical notes

  • VSCode extensions have a 100MB file size limit.

  • src/testFixtures/ is excluded in .vscode/settings.json, to prevent VSCode from treating its files as project files.

  • The codebase provides globals, which must be used instead of some common javascript globals. In particular, clock-related things like Date and setTimeout must not be used directly, instead use globals.clock.Date and globals.clock.setTimeout. #2343

  • VSCode extension examples: https://github.com/microsoft/vscode-extension-samples

  • Tests

    • Use function () and async function () syntax for describe() and it() callbacks instead of arrow functions.
    • Do NOT include any await functions in describe() blocks directly (usage in before, beforeEach, after, afterEach, and it blocks is fine).
      • await in describe() causes the framework to always evaluate the describe block and can cause issues with either tests not running or always running (if other tests are marked with .only)
      • Tests that require a premade value from a Promise should initialize the value as a let and make the awaited assignment in before().
  • How to debug unresolved promise rejections:

    1. Declare a global unhandledRejection handler.
      process.on('unhandledRejection', e => {
          getLogger('channel').error(
              localize(
                  'AWS.channel.aws.toolkit.activation.error',
                  'Error Activating {0} Toolkit: {1}',
                  getIdeProperties().company,
                  (e as Error).message
              )
          )
          if (e !== undefined) {
              throw e
          }
      })
    2. Put a breakpoint on it.
    3. Run all tests.

Test

See TESTPLAN.md to understand the project's test structure, mechanics and philosophy.

You can run tests directly from Visual Studio Code:

  1. Select View > Debug, or select the Debug pane from the sidebar.
  2. From the dropdown at the top of the Debug pane, select the Extension Tests configuration.
  3. Press F5 to run tests with the debugger attached.

You can also run tests from the command line:

npm run test
npm run integrationTest

Tests will write logs to ./.test-reports/testLog.log.

Run a specific test

To run a single test in VSCode, do any one of:

  • Run the Extension Tests (current file) launch-config.

  • Use Mocha's it.only() or describe.only().

  • Run in your terminal:

    • Unix/macOS/POSIX shell:
      TEST_FILE=src/test/foo.test npm run test
      
    • Powershell:
      $Env:TEST_FILE = "src/test/foo.test"; npm run test
      
  • To run all tests in a particular subdirectory, you can edit src/test/index.ts:rootTestsPath to point to a subdirectory:

    rootTestsPath: __dirname + '/shared/sam/debugger/'
    

Coverage report

You can find the coverage report at ./coverage/index.html after running the tests. Tests ran from the workspace launch config won't generate a coverage report automatically because it can break file watching. A few manual steps are needed instead:

  • Run the command Tasks: Run Build Task if not already active
  • Instrument built code with npm run instrument
  • Exercise the code (Extension Tests, Integration Tests, etc.)
  • Generate a report with npm run report

CodeCatalyst Blueprints

You can find documentation to create VSCode IDE settings for CodeCatalyst blueprints at docs/vscode-config.md.

Pull Requests

Before sending a pull request:

  1. Check that you are working against the latest source on the master branch.
  2. Check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already.
  3. Open an issue to discuss any significant work.

To send a pull request:

  1. Fork the repository.
  2. Modify the source; focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change.
  3. Commit to your fork using clear commit messages.
  4. Update the changelog by running npm run newChange.
    • Note: the main purpose of the newChange task is to avoid merge conflicts.
  5. Create a pull request.
  6. Pay attention to any CI failures reported in the pull request.

Commit messages

Generally your PR description should be a copy-paste of your commit message(s). If your PR description provides insight and context, that also should exist in the commit message. Source control (Git) is our source-of-truth, not GitHub.

Follow these commit message guidelines:

  • Subject: single line up to 50-72 characters

    • Imperative voice ("Fix bug", not "Fixed"/"Fixes"/"Fixing").
  • Body: for non-trivial or uncommon changes, explain your motivation for the change and contrast your implementation with previous behavior.

    • Often you can save a lot of words by using this simple template:
      Problem: …
      Solution: …
      

A good commit message has a short subject line and unlimited detail in the body. Good explanations are acts of creativity. The "tiny subject line" constraint reminds you to clarify the essence of the commit, and makes the log easy for humans to scan. The commit log is an artifact that will outlive most code.

Prefix the subject with type(topic): (conventional commits format): this again helps humans (and scripts) scan and omit ranges of the history at a glance.

CI artifact

Each commit and pull request is processed by an automated system which runs all tests and provides the build result via the Details link as shown below.

CI artifact

Tooling

Besides the typical develop/test/run cycle describe above, there are some tools for special cases such as build tasks, generating telemetry, generating SDKs, etc.

Toolkit developer settings (aws.dev.*)

The DevSettngs class defines various developer-only settings that change the behavior of the Toolkit for testing and development purposes. To use a setting just add it to your settings.json. At runtime, if the Toolkit reads any of these settings, the "AWS" statusbar item will change its color. Use the setting aws.dev.forceDevMode to trigger this effect on start-up.

Logging

The aws.dev.logfile setting allows you to set the path of the logfile. This makes it easy to follow and filter the logfile using shell tools like tail and grep. For example in settings.json,

"aws.dev.logfile": "~/awstoolkit.log",

then following the log with:

tail -F ~/awstoolkit.log

Service Endpoints

Endpoint overrides can be set per-service using the aws.dev.endpoints settings. This is a JSON object where each key is the service ID (case-insensitive) and each value is the endpoint. Refer to the SDK API models to find relevant service IDs.

Example:

"aws.dev.endpoints": {
    "s3": "http://example.com"
}

Telemetry and Automation

Metrics are only emitted if the extension is assumed to be ran from an actual user rather than automation scripts. This condition is checked through an environment variable AWS_TOOLKIT_AUTOMATION which is set by test entry points. If any truthy value is present, telemetry will be dropped if the current build is not a release version. Utility functions, such as assertTelemetry, can be used to test specific telemetry emits even in automation.

SAM/CFN ("goformation") JSON schema

See docs/cfn-schema-support.md for how to fix and improve the JSON schema that provides auto-completion and syntax checking of SAM and CloudFormation template.yaml files.

AWS SDK generator

When the AWS SDK does not (yet) support a service but you have an API model file (*.api.json), use generateServiceClient.ts to generate a TypeScript *.d.ts file and pass that to the AWS JS SDK to create requests just from the model/types.

  1. Add an entry to the list in generateServiceClient.ts:

     diff --git a/src/scripts/build/generateServiceClient.ts b/src/scripts/build/generateServiceClient.ts
     index 8bb278972d29..6c6914ec8812 100644
     --- a/src/scripts/build/generateServiceClient.ts
     +++ b/src/scripts/build/generateServiceClient.ts
     @@ -199,6 +199,10 @@ ${fileContents}
      ;(async () => {
          const serviceClientDefinitions: ServiceClientDefinition[] = [
     +        {
     +            serviceJsonPath: 'src/shared/foo.api.json',
     +            serviceName: 'ClientFoo'
     +        },
              {
                  serviceJsonPath: 'src/shared/telemetry/service-2.json',
                  serviceName: 'ClientTelemetry',
  2. Run the script:

    npm run generateClients
    
  3. The script produces a *.d.ts file (used only for IDE code-completion, not required to actually make requests):

    src/shared/foo.d.ts
    
  4. To make requests with the SDK, pass the *.api.json service model to globals.sdkClientBuilder.createAndConfigureServiceClient as a generic Service with apiConfig=require('foo.api.json').

    // Import the `*.d.ts` file for code-completion convenience.
    import * as ClientFoo from '../shared/clientfoo'
    // The AWS JS SDK uses this to dynamically build service requests.
    import apiConfig = require('../shared/foo.api.json')
    
    ...
    
    const c = await globals.sdkClientBuilder.createAwsService(
        opts => new Service(opts),
        {
            apiConfig: apiConfig,
            region: 'us-west-2',
            credentials: credentials,
            correctClockSkew: true,
            endpoint: 'foo-beta.aws.dev',
        }) as ClientFoo
    const req = c.getThing({ id: 'asdf' })
    req.send(function (err, data) { ... });

Webview dev-server

Webviews can be hot-reloaded (updated without restarting the extension) by running a developer server provided by webpack. This server is started automatically when running the Extension launch configuration. You can also start it by running npm serve. Note that only frontend components will be updated; if you change backend code you will still need to restart the development extension.

Font generation

For extensions to contribute their own codicons, VS Code requires a font file as well as how that font maps to codicon IDs. The mapping is found in package.json under the icons contribution point. Icons located in resources/icons are stitched together at build-time into a single font, automatically adding mappings to package.json. More information can be found here.

As a simple example, let's say I wanted to add a new icon for CloudWatch log streams. I would do the following:

  1. Place the icon in resources/icons/aws/cloudwatch. I'l name the icon log-stream.svg.

  2. Use npm run generatePackage to update package.json. Commit this change with the new icon.

  3. You can now use the icon in the Toolkit:

    getIcon('aws-cloudwatch-log-stream')

Beta artifacts

The Toolkit codebase contains logic in src/dev/beta.ts to support development during private betas. Creating a beta artifact requires a stable URL to source Toolkit builds from. This URL should be added to src/dev/config.ts. Subsequent Toolkit artifacts will have their version set to 1.999.0 with a commit hash. Builds will automatically query the URL to check for a new build once a day and on every reload.

VSCode Marketplace

The marketplace page is defined in README.quickstart.vscode.md (which replaces README.md during the release automation). The vsce package tool always replaces relative image paths with URLs pointing to HEAD on GitHub (https://github.com/aws/aws-toolkit-vscode/raw/HEAD/…/foo.gif).

Note therefore:

  1. Don't delete images from docs/marketplace/ unless the current published AWS Toolkit release doesn't depend on them.
  2. HEAD implies that the URL depends on the current default branch (i.e. master). Changes to other branches won't affect the marketplace page.

Importing icons from other open source repos

If you are contribuing visual assets from other open source repos, the source repo must have a compatible license (such as MIT), and we need to document the source of the images. Follow these steps:

  1. Use a separate location in this repo for every repo/organization where images are sourced from. See resources/icons/vscode as an example.

  2. Copy the source repo's licence into this destination location's LICENSE.txt file

  3. Create a README.md in the destination location, and type in a copyright attribution:

    The AWS Toolkit for VS Code includes the following third-party software/licensing:
    
    Icons contained in this folder and subfolders are from <SOURCE_REPO_NAME>: <SOURCE_REPO_URL>
    
    <PASTE_SOURCE_LICENSE_HERE>
    
  4. Add an entry here summarizing the new destination location, where the assets were sourced from, and a brief rationale.

PR #227 shows an example.

Code of Conduct

This project has adopted the Amazon Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

Security issues

If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via the vulnerability reporting page. Please do not create a public issue.

Licensing

See the LICENSE file for our project's licensing. We will ask you to confirm the licensing of your contribution.

We may ask you to sign a Contributor License Agreement (CLA) for larger changes.