UI: hackweek: add copilot instructions to ui repo (#8680) (#8728)

* add copilot instructions to repository

use copilot resources example repo (https://github.com/hashicorp/copilot-resources/tree/main)

* address PR comments (https://github.com/hashicorp/vault/pull/31361)

Co-authored-by: Shannon Roberts (Beagin) <beagins@users.noreply.github.com>
This commit is contained in:
Vault Automation 2025-09-02 15:29:45 -06:00 committed by GitHub
parent 2b469deeca
commit e47c5b5e39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 810 additions and 0 deletions

View file

@ -0,0 +1,88 @@
---
applyTo: "vault/ui/**/*"
description: "HashiCorp Ember.js UI general guidelines - project context, build structure, and cross-cutting concerns"
---
# HashiCorp Ember.js UI General Guidelines
This document provides general coding standards and project context for HashiCorp Ember.js UI applications. This serves as the central reference for project structure, framework information, and cross-cutting concerns.
> **Related Documents**: See domain-specific guidelines in `ember_javascript.instructions.md`, `ember_hbs.instructions.md`, `ember_styles.instructions.md`, and `ember_tests.instructions.md`.
## Project Context
HashiCorp Ember.js UI applications provide web-based interfaces for HashiCorp's infrastructure tools and cloud platforms. These applications serve enterprise-grade interfaces used by DevOps teams, platform engineers, security professionals, and system administrators to manage infrastructure, security policies, and operational workflows.
Applications use modern Ember Octane patterns, Handlebars templates, and SCSS for styling with the HashiCorp Design System components.
## Repository Structure
- `ui/app/components/` - Reusable UI components and their templates
- `ui/app/models/` - Ember Data models representing API entities
- `ui/app/routes/` - Route handlers for URL endpoints and data loading logic
- `ui/app/templates/` - Page-level Handlebars templates
- `ui/app/services/` - Ember services for shared functionality and state management
- `ui/app/helpers/` - Template helper functions for data formatting and logic
- `ui/tests/` - Integration, unit, and acceptance tests
- `ui/app/styles/` - SCSS stylesheets and component-specific styles
- `ui/config/` - Ember CLI configuration and environment settings
- `ui/mirage/` - Mock server configuration for development and testing
## Framework and Tools
- **Frontend Framework**: Ember.js 4.x with Ember Octane patterns and decorators
- **Data Layer**: Ember Data for API communication with backend services
- **Templating**: Handlebars templates with Ember's component architecture
- **Styling**: SCSS with HashiCorp Design System (HDS) components and Bulma CSS framework
- **Build System**: Ember CLI with Webpack for bundling and asset management
- **Development**: ESLint for code linting, Prettier for code formatting
## File Naming Conventions
- **Component Structure**: Components should have matching JavaScript/TypeScript and `.hbs` files in the same directory
- **Directory Organization**: Organize new components in logical subdirectories by feature or domain
## Build and Deployment Structure
- **Development Build**: `ember serve` creates development server with live reload
- **Production Build**: `ember build --environment=production` generates optimized assets in `dist/`
- **Asset Output**: Built files are typically served by the application's backend server or embedded in the main binary
- **Integration**: UI is often compiled and integrated into the main application during release builds
- **Testing**: `ember test` runs the full test suite with QUnit in headless Chrome
---
# Changelog Guidelines
For files in the `changelog/` directory:
- **Enterprise features**: Use `ui (enterprise): descriptive text`
- **Community features**: Use `ui: descriptive text`
- Always indicate enterprise-only features in the description
```javascript
// Changelog entries
"ui (enterprise): Add advanced policy filtering" // enterprise features
"ui: Fix configuration list pagination" // community features
```
---
# Dependency Management
## package.json Guidelines
- Pin exact versions for critical dependencies or use tilde (`~`) for patch updates only
- **WARNING**: Avoid caret (`^`) operator which allows minor version updates that may introduce breaking changes
- Use tilde (`~`) for regular dependencies, exact versions for security-critical packages
- Dependencies in `resolutions` block MUST be pinned (no `~` or `^`)
- Keep `package.json` changes minimal and focused on the specific feature or fix
- Always commit lock files (`yarn.lock`, `package-lock.json`) with dependency changes
- Ensure package.json changes are independent of other code changes (except lock files)
- **Reminder**: Consider coordinating dependency changes with backend teams when the UI is embedded in application binaries
Example dependency specification:
```json
{
"dependencies": {
"lodash": "4.17.21", // exact version for critical packages
"express": "~4.18.0" // tilde for patch updates only
},
"resolutions": {
"minimist": "1.2.6" // always exact for security fixes
}
}
```

View file

@ -0,0 +1,113 @@
---
applyTo: "vault/ui/**/*.hbs"
description: "HashiCorp Ember.js UI Handlebars template coding standards"
---
# HashiCorp Ember.js Handlebars Template Guidelines
This document provides Handlebars template coding standards for HashiCorp Ember.js UI applications.
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
## Template Best Practices
- Check truthiness of arrays directly instead of using `.length` property
- Use string interpolation `"prefix/{{value}}"` instead of `{{concat}}` helper
- Remove unnecessary quotes around dynamic component arguments
- Use `Hds::Link::Inline` for external documentation links instead of `<button>` elements
- Make `selected` attributes dynamic rather than static values - warn if static values are used
- Refactor conditionals to wrap content rather than entire elements when possible
- Avoid inline `style` attributes and `{{style ...}}` helpers - define CSS classes in `.scss` files instead
- Place `data-test-*` selectors as the last attribute on elements
- Remove quotes around dynamic data attributes: `data-test-id={{value}}` not `data-test-id="{{value}}"`
Examples:
```handlebars
{{!-- Good: direct array check --}}
{{#if this.model.allowed_roles}}
{{!-- Bad: unnecessary .length check --}}
{{#if (gt this.model.allowed_roles.length 0)}}
{{!-- Good: string interpolation --}}
@secret="role/{{@model.id}}"
{{!-- Bad: concat helper --}}
@secret={{concat "role/" @model.id}}
{{!-- Good: conditional content, not element --}}
<PH.Title>{{if this.version.isEnterprise "Enterprise" "Community"}} features</PH.Title>
{{!-- Bad: conditional wrapping entire element --}}
{{#if this.version.isEnterprise}}
<PH.Title>Enterprise features</PH.Title>
{{else}}
<PH.Title>Community features</PH.Title>
{{/if}}
{{!-- Good: CSS classes instead of inline styles --}}
<Hds::Button @text="Save" class="custom-button" data-test-save />
{{!-- Bad: inline style attribute --}}
<Hds::Button @text="Save" style="margin-top: 10px;" data-test-save />
{{!-- Bad: style helper --}}
<Hds::Button @text="Save" style={{style margin-top="10px"}} data-test-save />
{{!-- Good: data-test selector at the end --}}
<Hds::Button @text="Save" @icon="loading" disabled={{this.isLoading}} data-test-save />
{{!-- Bad: data-test selector not at the end --}}
<Hds::Button data-test-save @text="Save" @icon="loading" disabled={{this.isLoading}} />
{{!-- Good: no quotes around dynamic values --}}
<div data-test-namespace-link={{option.label}}>
{{!-- Bad: unnecessary quotes --}}
<div data-test-namespace-link="{{option.label}}">
```
---
# Content and Terminology
## Title and Heading Case Rules
- **USE SENTENCE CASE**: All HTML headings (`<h1>`, `<h2>`, `<h3>`, etc.) should use sentence case (only first letter capitalized)
- **NO TITLE CASE**: Avoid title case where every major word is capitalized
- **Component arguments**: Use sentence case for `@title`, `@label`, and similar text properties
- End descriptive text with proper punctuation
- Follow proper grammar rules including ending sentences with periods
- Use consistent terminology for product-specific features and components
Examples:
```handlebars
{{!-- CORRECT: Sentence case in HTML headings --}}
<h2 class="title is-4">Quick actions</h2>
<h3 class="title is-marginless is-6">Configuration settings</h3>
<h1>Authentication methods</h1>
{{!-- INCORRECT: Title case in HTML headings --}}
<h2 class="title is-4">Quick Actions</h2>
<h3 class="title is-marginless is-6">Configuration Settings</h3>
<h1>Authentication Methods</h1>
```
```javascript
// CORRECT: Sentence case in component arguments
@title="Upload user's profile"
@label="Configuration path"
@placeholder="Enter mount path"
// INCORRECT: Title case or inconsistent casing
@title="Upload User's Profile"
@label="Configuration Path"
@placeholder="Enter Mount Path"
```
```handlebars
{{!-- CORRECT: Sentence case in data-test attributes when they contain readable text --}}
data-test-card-subtitle="configuration-settings"
{{!-- Component usage with proper casing --}}
<Hds::Button @text="Create configuration" />
<Hds::Alert @message="Operation completed successfully" />
```

View file

@ -0,0 +1,100 @@
---
applyTo: "vault/ui/**/*.{js,ts}"
description: "HashiCorp Ember.js UI JavaScript and TypeScript coding standards"
---
# HashiCorp Ember.js JavaScript & TypeScript Guidelines
This document provides JavaScript and TypeScript coding standards for HashiCorp Ember.js UI applications.
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
## Documentation Standards
- Include JSDoc comments for all public functions, classes, and modules
- Use `/** @module ModuleName */` for modules and `/** description */` for functions
- Document function parameters, return types, and any side effects
- Keep comments concise and focused on the "why" rather than the "what"
- **Required**: Add documentation for all new files (components, helpers, services)
## Code Quality Standards
- Remove all unused imports, variables, and functions before committing
- Place comments directly above the code they describe, not inline or below
- Update comments when code changes to maintain accuracy
## TypeScript Guidelines
- **File Naming**: All new files should use `.ts` extension instead of `.js`
- **Migration Strategy**: When modifying existing `.js` files, evaluate the effort required to convert to `.ts` and prioritize conversion if time permits
- Use explicit types instead of `any` - prefer `unknown` for truly dynamic content
- Define interfaces for object shapes and function signatures
- Use type guards and discriminated unions for runtime type checking
- Enable strict mode in TypeScript configuration
## Modern Ember Patterns
- Replace `Route.extend`, `Model.extend`, or `Component.extend` with native JavaScript classes
- Use Ember Octane conventions: tracked properties, decorators, and native class syntax
- Create reusable components rather than one-off implementations
- Co-locate component templates (`.hbs`) with their TypeScript files (`.ts` preferred over `.js`)
- Prioritize reusability and maintainability when creating components - avoid overly complex or one-off implementations
## Asynchronous Programming
- Use `async`/`await` with proper error handling in `try`/`catch` blocks
- Only use `@task` from ember-concurrency when you need specific features like cancellation or `task.isRunning` state management
- Avoid `setTimeout` in favor of `requestAnimationFrame` for UI updates or proper async patterns for delays
- **Warning**: `setTimeout` is prone to testing issues and event loop management problems
- Handle promise rejections explicitly rather than relying on global handlers
## Date and Time Handling
- **WARNING**: Avoid `new Date()` as it uses the browser's timezone
- Use `Date.UTC()` constructor instead of `new Date()` for consistent timezone handling
- Use UTC methods like `getUTCFullYear()`, `getUTCMonth()` for date manipulation to ensure dates are calculated consistently
- Consider using a date library like `date-fns` for complex date operations
## Error Handling and Logging
- Use Ember's `assert` for runtime checks instead of `console.error`
- Avoid `console.error` in production code - use proper logging libraries or framework-specific methods
- Create meaningful error messages that include context about what failed
- Use structured logging with consistent log levels (debug, info, warn, error)
---
# Component Development (JavaScript/TypeScript)
## Component Architecture
- Use `@tracked` only for internal component state that changes over time
- Never use `@tracked` on component arguments (properties passed from parent components)
- Component class names must match their file names exactly
- Place `.hbs` templates in the same directory as their `.ts` files (or `.js` for legacy files) within `ui/app/components/`
- Organize new components in logical subdirectories by feature or domain
Examples:
```javascript
// Good: tracked for internal state
@tracked isExpanded = false;
// Bad: tracked on argument
@tracked @secret; // @secret is an argument, not internal state
```
---
# Model Definitions
## Ember Data Models
- Use single-line syntax for `@attr` declarations with simple options
- Avoid extra blank lines between consecutive single-line `@attr` declarations
- Group related attributes together logically
Example:
```javascript
// Good: compact single-line format
@attr('string', { label: 'Client ID' }) clientId;
@attr('string', { label: 'Client Secret' }) clientSecret;
@attr('boolean', { defaultValue: false }) isEnabled;
// Bad: unnecessary multi-line for simple attributes
@attr('string', {
label: 'Client ID',
}) clientId;
@attr('string', { label: 'Client Secret' }) clientSecret;
```

View file

@ -0,0 +1,36 @@
---
applyTo: "vault/ui/**/*.scss"
description: "HashiCorp Ember.js UI SCSS styling coding standards"
---
# HashiCorp Ember.js SCSS Styling Guidelines
This document provides SCSS styling coding standards for HashiCorp Ember.js UI applications.
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
## CSS Best Practices
- Avoid `z-index` - manage stacking order through DOM structure instead
- Avoid `!important` - use more specific selectors for overrides
Examples:
```scss
// Good: specific selector for overrides
.namespace-picker .button {
color: red;
}
// Bad: using !important
.button {
color: red !important;
}
// Bad: using z-index for stacking
.modal {
position: absolute;
z-index: 10;
}
// Good: manage stacking through DOM order in template
// Place modal element after background overlay in template
```

View file

@ -0,0 +1,225 @@
---
applyTo: "vault/ui/tests/**/*.{js,ts}"
description: "HashiCorp Ember.js testing standards and best practices"
---
# HashiCorp Ember.js Testing Standards
This document provides testing standards and best practices for HashiCorp Ember.js UI applications.
> **Note**: For general project context, framework information, and repository structure, see `ember_general.instructions.md`.
## Testing Framework and Tools
- **Testing Framework**: QUnit for unit, integration, and acceptance tests
- **Mock Server**: Ember CLI Mirage for API mocking and test data
- **Test Runners**: Ember CLI test runner with headless Chrome
## Test Directory Structure
- `ui/tests/integration/` - Component integration tests
- `ui/tests/unit/` - Service, helper, and model unit tests
- `ui/tests/acceptance/` - End-to-end user workflow tests
- `ui/mirage/` - Mock server configuration for development and testing
- `ui/tests/helpers/` - Custom test helper functions and utilities
---
# Testing Standards
## Test Quality
- Use `assert.true()` or `assert.false()` instead of `assert.ok()` for boolean checks
- Provide descriptive assertion messages that explain what is being verified
- Use `data-test-*` selectors for DOM interactions to decouple from styling
- Place `this.server` setup at the top of test blocks when using ember-cli-mirage
- Interact with elements directly rather than using Page Object patterns
Example test assertions:
```javascript
// Good: specific assertion with descriptive message
assert.true(component.isVisible, 'Component should be visible after clicking toggle');
// Bad: vague assertion without context
assert.ok(component.isVisible);
```
## Asynchronous Testing
- Use Ember's `run.later` instead of `setTimeout` in tests for better runloop control
- Handle async operations with proper waiting patterns in tests
- Ensure test isolation by resetting state between tests
## Mirage Server Setup
- **Use `setupMirage(hooks)`** to automatically manage server lifecycle - no manual shutdown required
- Place `this.server` setup at the top of test blocks when using ember-cli-mirage
- Configure mock data that reflects realistic API responses
- Use mirage factories for generating test data consistently
- Reset server state between tests to ensure test isolation
**Recommended approach** - use `setupMirage()`:
```javascript
import { setupMirage } from 'ember-cli-mirage/test-support';
module('Integration | Component | my-component', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks); // Automatically handles server setup and shutdown
hooks.beforeEach(function () {
this.server.create('model', { id: 1, name: 'Test Item' });
});
});
```
> **Note**: Avoid manual server setup and shutdown. Use `setupMirage(hooks)` instead to prevent memory leaks and reduce boilerplate code.
## DOM Testing Best Practices
- Use `data-test-*` selectors for DOM interactions to decouple from styling
- Test user interactions through realistic user flows
- Verify state changes after user actions
- Test error states and edge cases
- Ensure accessibility features work correctly
Example DOM testing:
```javascript
// Good: using data-test selectors
await click('[data-test-submit-button]');
assert.true(find('[data-test-success-message]'), 'Success message should appear after submission');
// Bad: using CSS classes for testing
await click('.btn-submit');
assert.ok(find('.alert-success'));
```
## Test Organization
- **Use modules primarily for shared test setup and context**, not just organizational grouping
- Nest modules only when tests benefit from the same `beforeEach` context or setup logic
- Avoid excessive nesting that can make test structure confusing to navigate
- Use descriptive test names that explain the scenario being tested
- Include both positive and negative test cases
- Test error handling and edge cases
- Keep tests focused on a single behavior or outcome
**Good module usage** - shared setup benefits multiple tests:
```javascript
module('Integration | Component | secret-form', function (hooks) {
setupRenderingTest(hooks);
setupMirage(hooks);
module('with authentication', function (hooks) {
hooks.beforeEach(function () {
// Shared setup that multiple tests need
this.server.create('user', { authenticated: true });
this.store = this.owner.lookup('service:store');
this.currentUser = this.store.createRecord('user', { id: 1 });
});
test('shows user-specific options when authenticated', function (assert) {
// Test that benefits from the shared authentication setup
});
test('allows advanced actions when authenticated', function (assert) {
// Another test that needs the same authentication context
});
});
module('without authentication', function (hooks) {
hooks.beforeEach(function () {
// Different shared setup for unauthenticated state
this.server.create('user', { authenticated: false });
});
test('hides sensitive options when not authenticated', function (assert) {
// Test that benefits from unauthenticated setup
});
});
});
```
**Avoid** - unnecessary nesting for organization only:
```javascript
// Don't do this - no shared setup benefit
module('Integration | Component | secret-form', function (hooks) {
module('input validation', function (hooks) {
test('validates required fields', function (assert) { /* ... */ });
test('validates field format', function (assert) { /* ... */ });
});
module('form submission', function (hooks) {
test('submits valid data', function (assert) { /* ... */ });
test('handles submission errors', function (assert) { /* ... */ });
});
});
```
Example test structure:
```javascript
module('Integration | Component | secret-form', function (hooks) {
setupRenderingTest(hooks);
test('it displays validation error when secret name is empty', async function (assert) {
await render(hbs`<SecretForm @onSubmit={{this.handleSubmit}} />`);
await click('[data-test-submit-button]');
assert.true(
find('[data-test-name-error]').textContent.includes('Secret name is required'),
'Should display validation error for empty secret name'
);
});
test('it calls onSubmit with form data when valid', async function (assert) {
let submittedData;
this.handleSubmit = (data) => { submittedData = data; };
await render(hbs`<SecretForm @onSubmit={{this.handleSubmit}} />`);
await fillIn('[data-test-secret-name]', 'my-secret');
await fillIn('[data-test-secret-value]', 'secret-value');
await click('[data-test-submit-button]');
assert.deepEqual(submittedData, {
name: 'my-secret',
value: 'secret-value'
}, 'Should submit form data with correct values');
});
});
```
---
# Debugging Tests
## Debugging Tips
When debugging Ember templates in tests:
- Use `{{debugger}}` inside templates to inspect values in the browser console
- In the console during debugging:
- Use `get('property.name')` to inspect nested properties
- Use `context` to explore the current template context
- Add console.log statements in test code to track execution flow
- Use browser developer tools to inspect DOM state during test execution
Example debugging usage:
```handlebars
{{#each this.items as |item|}}
{{debugger}}
{{/each}}
```
```javascript
test('debugging example', async function (assert) {
await render(hbs`<MyComponent @data={{this.testData}} />`);
// Pause execution to inspect DOM
debugger;
console.log('Component state:', this.element.querySelector('[data-test-component]'));
await click('[data-test-button]');
// Inspect state after interaction
debugger;
});
```
## Test Isolation
- Reset component state between tests
- Clear any global state or services
- Ensure tests don't depend on execution order
- Use hooks for setup and teardown consistently

View file

@ -0,0 +1,158 @@
---
applyTo: "**/*.go"
description: "Practical guidance for Golang programming"
---
# Go Programming Instructions
## Code Style and Formatting
- Use `gofmt` and `goimports` to format all Go code automatically
- Follow standard Go naming conventions:
- camelCase for unexported identifiers
- PascalCase for exported identifiers
- Use MixedCaps or mixedCaps rather than underscores for multiword names
- Words in names that are initialisms or acronyms (e.g. “URL” or “NATO”) have a consistent case. For example, “URL” should appear as “URL” or “url” (as in “urlPony”, or “URLPony”), never as “Url”. As an example: ServeHTTP not ServeHttp. For identifiers with multiple initialized “words”, use for example “xmlHTTPRequest” or “XMLHTTPRequest”.
- Keep line length reasonable (Go has no strict limit, but wrap long lines)
- Use meaningful variable and function names
## Package Organization
- Use lowercase, single-word package names, no hyphens or underscores
- Keep packages focused and cohesive
- Place main packages in `cmd/` directory for applications, unless the repository will only ever contain one executable, in which case a `main.go` at the root of the repository is ok
- Package name should be the base name of its source directory
## Naming Conventions
### Package Names
- Use short, concise, evocative names
- Prefer brevity since everyone using your package will type the name
- Examples: `bufio.Reader` not `bufio.BufReader`, `ring.New` not `ring.NewRing`
### Interface Names
- One-method interfaces use method name + "-er" suffix: `Reader`, `Writer`, `Formatter`
- Honor canonical method signatures: `Read`, `Write`, `Close`, `String`
### Getters and Setters
- Prefer exporting fields over adding getters and setters where possible
- When required, don't use "Get" prefix for getters. For example, if the field name is `owner`, the getter should be `Owner()`, and the setter `SetOwner()`
## Functions and Methods
- Use multiple return values to improve error handling
- Only use named result parameters if multiple parameters are of the same type
- Use defer for cleanup operations (closing files, unlocking mutexes)
- Defer executes in LIFO order
- Arguments to deferred functions are evaluated when defer executes
## Control Structures
- Use initialization statement in if/switch when appropriate:
```go
if err := file.Chmod(0o664); err != nil {
return err
}
```
- Use switch statements instead of repeated if statements for validation:
```go
// Good:
switch {
case x < 0: return fmt.Errorf("negative value")
case x > 10: return fmt.Errorf("value too large")
}
// Bad:
if x < 0 { return fmt.Errorf("negative value") }
if x > 10 { return fmt.Errorf("value too large") }
```
- Omit unnecessary else statements when if ends with return/break/continue
- Use type switches for interface type checking
- Use range for iteration over arrays, slices, strings, maps, channels
```go
for i, v := range slice { /* ... */ } // Good
for i := 0; i < len(slice); i++ { /* ... */ } // Bad
```
## Error Handling and Design
- Always handle errors explicitly
- Use descriptive error messages that include context
- Wrap errors with additional context when appropriate
- Return errors as the last return value
- Check error returns - they're provided for a reason
- Use the "comma ok" idiom for optional error checking:
```go
if value, ok := someOperation(); !ok {
// handle error case
}
```
- Implement the error interface, `Is(error) bool` and `As(any) bool` for custom error types
- Provide detailed error context including operation and file paths
- Use panic only for truly exceptional cases or programming errors
- Use recover to handle panics gracefully in server applications
- Design errors to be useful when printed far from their origin
## Data Structures
- Prefer zero-value-useful types in your designs
- Prefer slices over arrays for most use cases
- Understand slice sharing and capacity
- Use `append()` built-in for growing slices
- Use copy() for copying slice elements
- Maps
- Use "comma ok" idiom to test for presence: `value, ok := m[key]`
- Use `delete(m, key)` to remove entries safely
## Interfaces and Composition
- Design small, focused interfaces (often single-method)
- Accept interfaces, return concrete types
- Use empty interface `interface{}` or `any` sparingly
- Prefer composition over large interfaces
- Use type assertions and type switches for interface conversions
- Embed types to promote methods and satisfy interfaces
- Use embedding for has-a relationships, not is-a
- Understand method promotion and shadowing rules
## Concurrency
- Don't communicate by sharing memory; share memory by communicating
- Use channels for goroutine communication and synchronization
- Use goroutines for concurrent execution: `go functionCall()`
- Use buffered channels as semaphores for limiting concurrency
- Use select for non-blocking channel operations
- Prefer structured concurrency patterns over ad-hoc goroutine creation
- Unbuffered channels provide synchronization
- Buffered channels can improve performance and provide semaphore behavior
- Close channels to signal completion to range loops
## Documentation
- Write clear godoc comments for exported functions and types
- Start comments with the name of the item being documented
- Use complete sentences in documentation
- Provide examples in documentation when helpful
- Document any unusual behavior or requirements
## Best Practices
- Keep functions small and focused
- Use context for cancellation and timeouts
- Avoid global variables when possible
- Use the blank identifier `_` to discard unused values
- Make zero values useful in your type designs
- Use init() functions for package initialization
- Initialize complex data with composite literals
- Profile before optimizing
- Use build constraints for platform-specific code
- Understand escape analysis and stack vs heap allocation
- Use sync.Pool for frequently allocated objects
## Common Idioms
- Use `fmt.Stringer` interface for custom string representations
- Implement `io.Reader` and `io.Writer` interfaces when appropriate
- Use functional options pattern for configuration
- Use builder pattern for complex object construction
- Prefer early returns to reduce nesting
- Initialize complex data with composite literals
### Type Embedding
- Embed types to promote methods and satisfy interfaces
- Use embedding for has-a relationships, not is-a
- Understand method promotion and shadowing rules
### Performance
- Understand escape analysis and stack vs heap allocation
- Use sync.Pool for frequently allocated objects
- Profile before optimizing
- Use build constraints for platform-specific code

View file

@ -0,0 +1,29 @@
---
applyTo: "**/*_test.go"
description: "Practical guidance for writing tests in Go"
---
# Golang Testing Guidelines
*Practical guidance for writing tests in Go*
## General Guidelines
- Write unit tests for all public functions
- Use table-driven tests when appropriate
- Follow naming convention: `Test_FunctionName`
- Use `t.Parallel()` for faster test execution and to encourage writing tests that don't share state
## Tools
- Use testify/assert and testify/require for consistent assertions
## Test Structure
- Use t.Helper() to mark helper functions
- Use subtests for organizing related test cases with t.Run()
## Integration Tests
- Use testcontainers to spin up dependencies like postgres or redis
## Black box testing
- The test should be in feature_test package to be the first client of the feature package
## End-to-End Testing (Future Enhancement)
<!-- TODO: Add guidance for end-to-end testing with enos and cloud-first testing in Vault Cloud -->

View file

@ -0,0 +1,45 @@
---
applyTo: "**/*_test.go,**/*_spec.rb"
description: "Practical guidance for writing tests across languages"
---
# Philosophy & Principles
## Testing:
- Test coverage is not a metric to optimize for
- Test behavior and not implementation detail
- Write tests that are robust to refactoring the code under test
### Value of a test
- Test is code that needs to be maintained
- If a test is not valuable, delete it
### Tests are documentation
- Use the given-when-then pattern to communicate each test case
- Test names should express intent
## Test Design & Quality
*How to design reliable, maintainable tests*
### Test Isolation
- A unit test should only fail for one reason
- Do not share state between tests
- Cleanup resources after the test
- If files are needed, use a temp directory (in Go, prefer `t.TempDir()` for automatic cleanup)
### Test Stability
- Do not use sleeping in a test
### Test Structure
- Consider parametrized tests where it makes sense
### Mocks
- Preferably do not use mocks
- If you use mocks, assert the mock expectations
## Supporting Code Quality
*Making the code under test more testable*
### Code under test
- If the code relies on magic numbers or constants: Extract them
- Consider introducing interfaces

16
.github/instructions/index.md vendored Normal file
View file

@ -0,0 +1,16 @@
# Instructions
## Generic
The generic folder contains instructions that can simply be copied into your teams repo for reuse. They are generic problem solving rules.
- golang_test.instructions.md
Best practice for writing tests in Golang
## Specific
The specific folder contains instructions that are not intended for reuse.
config.instructions.md
Guidance for the pkg/config package in the terraform-enterprise repository, providing additional context, such as the requirement to consider backwards compatability.
style.instructions.md
Guidance for writing documentation. Used in the web-unified-docs-internal repo.