mirror of
https://github.com/denoland/deno.git
synced 2025-12-23 08:48:24 +00:00
chore: allow triggering pr generation manually, tweak pr generation workflow, add claude.md (#31217)
This commit is contained in:
parent
ac62d1dca3
commit
cf4379d047
2 changed files with 433 additions and 10 deletions
58
.github/workflows/ai_pr_generation.yml
vendored
58
.github/workflows/ai_pr_generation.yml
vendored
|
|
@ -3,10 +3,16 @@ name: AI PR Generation
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [labeled]
|
types: [labeled]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
issue_number:
|
||||||
|
description: 'Issue number or URL to work on'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate-pr:
|
generate-pr:
|
||||||
if: github.event.label.name == 'ai:generate-pr'
|
if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'ai:generate-pr'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
|
@ -18,6 +24,38 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Get issue details
|
||||||
|
id: issue
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
# Extract issue number from input (handles both URLs and plain numbers)
|
||||||
|
ISSUE_INPUT="${{ inputs.issue_number }}"
|
||||||
|
ISSUE_NUM=$(echo "$ISSUE_INPUT" | grep -oE '[0-9]+$' || echo "$ISSUE_INPUT")
|
||||||
|
|
||||||
|
# Fetch issue details
|
||||||
|
ISSUE_JSON=$(gh issue view "$ISSUE_NUM" --json number,title,body,author --repo ${{ github.repository }})
|
||||||
|
echo "number=$(echo "$ISSUE_JSON" | jq -r '.number')" >> $GITHUB_OUTPUT
|
||||||
|
echo "title=$(echo "$ISSUE_JSON" | jq -r '.title')" >> $GITHUB_OUTPUT
|
||||||
|
echo "author=$(echo "$ISSUE_JSON" | jq -r '.author.login')" >> $GITHUB_OUTPUT
|
||||||
|
# Handle multiline body by base64 encoding
|
||||||
|
echo "body=$(echo "$ISSUE_JSON" | jq -r '.body' | base64 -w 0)" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
# Use event data for label trigger
|
||||||
|
echo "number=${{ github.event.issue.number }}" >> $GITHUB_OUTPUT
|
||||||
|
echo "title=${{ github.event.issue.title }}" >> $GITHUB_OUTPUT
|
||||||
|
echo "author=${{ github.event.issue.user.login }}" >> $GITHUB_OUTPUT
|
||||||
|
echo "body=$(echo '${{ github.event.issue.body }}' | base64 -w 0)" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Decode issue body
|
||||||
|
id: decoded
|
||||||
|
run: |
|
||||||
|
echo "body<<EOF" >> $GITHUB_OUTPUT
|
||||||
|
echo "${{ steps.issue.outputs.body }}" | base64 -d >> $GITHUB_OUTPUT
|
||||||
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- uses: anthropics/claude-code-action@v1
|
- uses: anthropics/claude-code-action@v1
|
||||||
with:
|
with:
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
|
|
@ -25,15 +63,15 @@ jobs:
|
||||||
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||||
prompt: |
|
prompt: |
|
||||||
REPO: ${{ github.repository }}
|
REPO: ${{ github.repository }}
|
||||||
ISSUE NUMBER: ${{ github.event.issue.number }}
|
ISSUE NUMBER: ${{ steps.issue.outputs.number }}
|
||||||
TITLE: ${{ github.event.issue.title }}
|
TITLE: ${{ steps.issue.outputs.title }}
|
||||||
BODY: ${{ github.event.issue.body }}
|
BODY: ${{ steps.decoded.outputs.body }}
|
||||||
AUTHOR: ${{ github.event.issue.user.login }}
|
AUTHOR: ${{ steps.issue.outputs.author }}
|
||||||
|
|
||||||
You have been assigned to work on fixing this issue. Your goal is to:
|
You have been assigned to work on fixing this issue. Your goal is to:
|
||||||
|
|
||||||
1. **FIRST: Check for specific implementation instructions**: Before doing anything else, fetch all comments on this issue using:
|
1. **FIRST: Check for specific implementation instructions**: Before doing anything else, fetch all comments on this issue using:
|
||||||
`gh issue view ${{ github.event.issue.number }} --comments`
|
`gh issue view ${{ steps.issue.outputs.number }} --comments`
|
||||||
|
|
||||||
Look for any comments that contain the "**AI PR instruction**" banner. These comments contain specific
|
Look for any comments that contain the "**AI PR instruction**" banner. These comments contain specific
|
||||||
implementation guidance from maintainers that MUST take precedence over all other context.
|
implementation guidance from maintainers that MUST take precedence over all other context.
|
||||||
|
|
@ -60,14 +98,14 @@ jobs:
|
||||||
- If tests fail, debug and fix them
|
- If tests fail, debug and fix them
|
||||||
|
|
||||||
6. **Create a pull request**: Once your changes are ready:
|
6. **Create a pull request**: Once your changes are ready:
|
||||||
- Create a new branch with a descriptive name (e.g., `fix-issue-${{ github.event.issue.number }}`)
|
- Create a new branch with a descriptive name (e.g., `fix-issue-${{ steps.issue.outputs.number }}`)
|
||||||
- Commit your changes with a clear commit message
|
- Commit your changes with a clear commit message
|
||||||
- Push the branch and create a PR with:
|
- Push the branch and create a PR with:
|
||||||
- Title that references the issue: "Fix #${{ github.event.issue.number }}: [brief description]"
|
- Title that references the issue: "Fix #${{ steps.issue.outputs.number }}: [brief description]"
|
||||||
- Description explaining what was changed and why
|
- Description explaining what was changed and why
|
||||||
- Reference to the original issue
|
- Reference to the original issue
|
||||||
|
|
||||||
7. **Comment on the issue**: After creating the PR, add a comment to issue #${{ github.event.issue.number }} with:
|
7. **Comment on the issue**: After creating the PR, add a comment to issue #${{ steps.issue.outputs.number }} with:
|
||||||
- A link to the PR you created
|
- A link to the PR you created
|
||||||
- A brief summary of the changes made
|
- A brief summary of the changes made
|
||||||
- Include this banner: "_This PR was autogenerated and may require review and adjustments._"
|
- Include this banner: "_This PR was autogenerated and may require review and adjustments._"
|
||||||
|
|
@ -82,4 +120,4 @@ jobs:
|
||||||
You have access to the full repository and can use git, cargo, and gh CLI commands.
|
You have access to the full repository and can use git, cargo, and gh CLI commands.
|
||||||
|
|
||||||
claude_args: |
|
claude_args: |
|
||||||
--allowedTools "Bash(git:*),Bash(cargo test:*),Bash(cargo build:*),Bash(cargo check:*),Bash(gh pr:*),Bash(gh issue:*),Bash(grep:*),Bash(find:*)"
|
--dangerously-skip-permissions --allowed-tools "*"
|
||||||
|
|
|
||||||
385
CLAUDE.md
Normal file
385
CLAUDE.md
Normal file
|
|
@ -0,0 +1,385 @@
|
||||||
|
# Deno Development Guide
|
||||||
|
|
||||||
|
## Table of Contents
|
||||||
|
|
||||||
|
- [High Level Overview](#high-level-overview)
|
||||||
|
- [Quick Start](#quick-start)
|
||||||
|
- [Commands](#commands)
|
||||||
|
- [Testing](#testing)
|
||||||
|
- [Development Workflows](#development-workflows)
|
||||||
|
- [Debugging](#debugging)
|
||||||
|
- [Codebase Navigation](#codebase-navigation)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
|
||||||
|
## High Level Overview
|
||||||
|
|
||||||
|
The user visible interface and high level integration is in the `deno` crate
|
||||||
|
(located in `./cli`).
|
||||||
|
|
||||||
|
This includes flag parsing, subcommands, package management tooling, etc. Flag
|
||||||
|
parsing is in `cli/args/flags.rs`. Tools are in `cli/tools/<tool>`.
|
||||||
|
|
||||||
|
The `deno_runtime` crate (`./runtime`) assembles the javascript runtime,
|
||||||
|
including all of the "extensions" (native functionality exposed to javascript).
|
||||||
|
The extensions themselves are in the `ext/` directory, and provide system access
|
||||||
|
to javascript – for instance filesystem operations and networking.
|
||||||
|
|
||||||
|
### Key Directories
|
||||||
|
|
||||||
|
- `cli/` - User-facing CLI implementation, subcommands, and tools
|
||||||
|
- `runtime/` - JavaScript runtime assembly and integration
|
||||||
|
- `ext/` - Extensions providing native functionality to JS (fs, net, etc.)
|
||||||
|
- `tests/specs/` - Integration tests (spec tests)
|
||||||
|
- `tests/unit/` - Unit tests
|
||||||
|
- `tests/testdata/` - Test fixtures and data files
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Building Deno
|
||||||
|
|
||||||
|
To compile after making changes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build
|
||||||
|
```
|
||||||
|
|
||||||
|
For faster iteration during development (less optimization):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo build --bin deno
|
||||||
|
```
|
||||||
|
|
||||||
|
Execute your development build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./target/debug/deno eval 'console.log("Hello from dev build")'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Running with your changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run a local file
|
||||||
|
./target/debug/deno run path/to/file.ts
|
||||||
|
|
||||||
|
# Run with permissions
|
||||||
|
./target/debug/deno run --allow-net --allow-read script.ts
|
||||||
|
|
||||||
|
# Run the REPL
|
||||||
|
./target/debug/deno
|
||||||
|
```
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
### Compilation and Checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check for compilation errors (fast, no binary output)
|
||||||
|
cargo check
|
||||||
|
|
||||||
|
# Check specific package
|
||||||
|
cargo check -p deno_runtime
|
||||||
|
|
||||||
|
# Build release version (slow, optimized)
|
||||||
|
cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Lint the code
|
||||||
|
./tools/lint.js
|
||||||
|
|
||||||
|
# Format the code
|
||||||
|
./tools/format.js
|
||||||
|
|
||||||
|
# Both lint and format
|
||||||
|
./tools/format.js && ./tools/lint.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all tests (this takes a while)
|
||||||
|
cargo test
|
||||||
|
|
||||||
|
# Filter tests by name
|
||||||
|
cargo test <nameOfTest>
|
||||||
|
|
||||||
|
# Run tests in a specific package
|
||||||
|
cargo test -p deno_core
|
||||||
|
|
||||||
|
# Run just the CLI integration tests
|
||||||
|
cargo test --bin deno
|
||||||
|
|
||||||
|
# Run spec tests only
|
||||||
|
cargo test specs
|
||||||
|
|
||||||
|
# Run a specific spec test
|
||||||
|
cargo test spec::test_name
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test Organization
|
||||||
|
|
||||||
|
- **Spec tests** (`tests/specs/`) - Main integration tests, CLI command
|
||||||
|
execution and output validation
|
||||||
|
- **Unit tests** - Inline with source code in each module
|
||||||
|
- **Integration tests** (`cli/tests/`) - Additional integration tests
|
||||||
|
- **WPT** (`tests/wpt/`) - Web Platform Tests for web standards compliance
|
||||||
|
|
||||||
|
## "spec" tests
|
||||||
|
|
||||||
|
The main form of integration test in deno is the "spec" test. These tests can be
|
||||||
|
found in `tests/specs`. The idea is that you have a `__test__.jsonc` file that
|
||||||
|
lays out one or more tests, where a test is a CLI command to execute and the
|
||||||
|
output is captured and asserted against.
|
||||||
|
|
||||||
|
The name of the test comes from the directory the `__test__.jsonc` appears in.
|
||||||
|
|
||||||
|
### Creating a New Spec Test
|
||||||
|
|
||||||
|
1. Create a directory in `tests/specs/` with a descriptive name
|
||||||
|
2. Add a `__test__.jsonc` file describing your test steps
|
||||||
|
3. Add any input files needed for the test
|
||||||
|
4. Add `.out` files for expected output (or inline in `__test__.jsonc`)
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
tests/specs/my_feature/
|
||||||
|
__test__.jsonc
|
||||||
|
main.ts
|
||||||
|
expected.out
|
||||||
|
```
|
||||||
|
|
||||||
|
### `__test__.jsonc` schema
|
||||||
|
|
||||||
|
The schema for `__test__.jsonc` can be found in `tests/specs/schema.json`.
|
||||||
|
|
||||||
|
Example test structure:
|
||||||
|
|
||||||
|
```jsonc
|
||||||
|
{
|
||||||
|
"tests": {
|
||||||
|
"basic_case": {
|
||||||
|
"args": "run main.ts",
|
||||||
|
"output": "expected.out"
|
||||||
|
},
|
||||||
|
"with_flag": {
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"args": "run --allow-net main.ts",
|
||||||
|
"output": "[WILDCARD]success[WILDCARD]"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output assertions
|
||||||
|
|
||||||
|
The expected output can be inline in a `__test__.jsonc` file or in a file ending
|
||||||
|
with `.out`. For a given test step, the `output` field tells you either the
|
||||||
|
inline expectation or the name of the file containing the **expectation**. The
|
||||||
|
expectation uses a small matching language to support wildcards and things like
|
||||||
|
that. A literal character means you expect that exact character, so `Foo bar`
|
||||||
|
would expect the output to be "Foo bar". Then there are things with special
|
||||||
|
meanings:
|
||||||
|
|
||||||
|
- `[WILDCARD]` : matches 0 or more of any character, like `.*` in regex. this
|
||||||
|
can cross newlines
|
||||||
|
- `[WILDLINE]` : matches 0 or more of any character, ending at the end of a line
|
||||||
|
- `[WILDCHAR]` - match the next character
|
||||||
|
- `[WILDCHARS(5)]` - match any of the next 5 characters
|
||||||
|
- `[UNORDERED_START]` followed by many lines then `[UNORDERED_END]` will match
|
||||||
|
the lines in any order (useful for non-deterministic output)
|
||||||
|
- `[# example]` - line comments start with `[#` and end with `]`
|
||||||
|
|
||||||
|
Example `.out` file:
|
||||||
|
|
||||||
|
```
|
||||||
|
Check file://[WILDCARD]/main.ts
|
||||||
|
[WILDCARD]
|
||||||
|
Successfully compiled [WILDLINE]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Workflows
|
||||||
|
|
||||||
|
### Adding a New CLI Subcommand
|
||||||
|
|
||||||
|
1. Define the command structure in `cli/args/flags.rs`
|
||||||
|
2. Add the command handler in `cli/tools/<command_name>.rs` or
|
||||||
|
`cli/tools/<command_name>/mod.rs`
|
||||||
|
3. Wire it up in `cli/main.rs`
|
||||||
|
4. Add spec tests in `tests/specs/<command_name>/`
|
||||||
|
|
||||||
|
Example files to reference:
|
||||||
|
|
||||||
|
- Simple command: `cli/tools/fmt.rs`
|
||||||
|
- Complex command: `cli/tools/test/`
|
||||||
|
|
||||||
|
### Modifying or Adding an Extension
|
||||||
|
|
||||||
|
1. Navigate to `ext/<extension_name>/` (e.g., `ext/fs/`, `ext/net/`)
|
||||||
|
2. Rust code provides the ops (operations) exposed to JavaScript
|
||||||
|
3. JavaScript code in the extension provides the higher-level APIs
|
||||||
|
4. Update `runtime/worker.rs` to register the extension if new
|
||||||
|
5. Add tests in the extension's directory
|
||||||
|
|
||||||
|
### Updating Dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update Cargo dependencies
|
||||||
|
cargo update
|
||||||
|
|
||||||
|
# Update to latest compatible versions
|
||||||
|
cargo upgrade # Requires cargo-edit: cargo install cargo-edit
|
||||||
|
|
||||||
|
# Check for outdated dependencies
|
||||||
|
cargo outdated # Requires cargo-outdated
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging
|
||||||
|
|
||||||
|
### Debugging Rust Code
|
||||||
|
|
||||||
|
Use your IDE's debugger (VS Code with rust-analyzer, IntelliJ IDEA, etc.):
|
||||||
|
|
||||||
|
1. Set breakpoints in Rust code
|
||||||
|
2. Run tests in debug mode through your IDE
|
||||||
|
3. Or use `lldb` directly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
lldb ./target/debug/deno
|
||||||
|
(lldb) run eval 'console.log("test")'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debugging JavaScript Runtime Issues
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Enable V8 inspector
|
||||||
|
./target/debug/deno run --inspect-brk script.ts
|
||||||
|
|
||||||
|
# Then connect Chrome DevTools to chrome://inspect
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use println debugging.
|
||||||
|
|
||||||
|
### Verbose Logging
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set Rust log level
|
||||||
|
DENO_LOG=debug ./target/debug/deno run script.ts
|
||||||
|
|
||||||
|
# Specific module logging
|
||||||
|
DENO_LOG=deno_core=debug ./target/debug/deno run script.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Prints
|
||||||
|
|
||||||
|
In Rust code:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
eprintln!("Debug: {:?}", some_variable);
|
||||||
|
dbg!(some_variable);
|
||||||
|
```
|
||||||
|
|
||||||
|
In the JavaScript runtime:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
console.log("Debug:", value);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Codebase Navigation
|
||||||
|
|
||||||
|
### Key Files to Understand First
|
||||||
|
|
||||||
|
1. `cli/main.rs` - Entry point, command routing
|
||||||
|
2. `cli/args/flags.rs` - CLI flag parsing and structure
|
||||||
|
3. `runtime/worker.rs` - Worker/runtime initialization
|
||||||
|
4. `runtime/permissions.rs` - Permission system
|
||||||
|
5. `cli/module_loader.rs` - Module loading and resolution
|
||||||
|
|
||||||
|
### Common Patterns
|
||||||
|
|
||||||
|
- **Ops** - Rust functions exposed to JavaScript (in `ext/` directories)
|
||||||
|
- **Extensions** - Collections of ops and JS code providing functionality
|
||||||
|
- **Workers** - JavaScript execution contexts (main worker, web workers)
|
||||||
|
- **Resources** - Managed objects passed between Rust and JS (files, sockets,
|
||||||
|
etc.)
|
||||||
|
|
||||||
|
### Finding Examples
|
||||||
|
|
||||||
|
- Need to add a CLI flag? Look at similar commands in `cli/args/flags.rs`
|
||||||
|
- Need to add an op? Look at ops in relevant `ext/` directory (e.g.,
|
||||||
|
`ext/fs/lib.rs`)
|
||||||
|
- Need to add a tool? Reference existing tools in `cli/tools/`
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Build Failures
|
||||||
|
|
||||||
|
**Error: linking with `cc` failed**
|
||||||
|
|
||||||
|
- Make sure you have the required system dependencies
|
||||||
|
- On macOS: `xcode-select --install`
|
||||||
|
- On Linux: Install `build-essential` or equivalent
|
||||||
|
|
||||||
|
**Error: failed to download dependencies**
|
||||||
|
|
||||||
|
- Check internet connection
|
||||||
|
- Try `cargo clean` then rebuild
|
||||||
|
- Check if behind a proxy, configure cargo accordingly
|
||||||
|
|
||||||
|
### Test Failures
|
||||||
|
|
||||||
|
**Spec test failures**
|
||||||
|
|
||||||
|
- Check the test output carefully for differences
|
||||||
|
- Update `.out` files if output format changed intentionally
|
||||||
|
- Use `[WILDCARD]` for non-deterministic parts of output
|
||||||
|
|
||||||
|
**Flaky tests**
|
||||||
|
|
||||||
|
- Add `[UNORDERED_START]`/`[UNORDERED_END]` for order-independent output
|
||||||
|
- Check for race conditions in test code
|
||||||
|
- May need to increase timeouts or add retries
|
||||||
|
|
||||||
|
### Permission Issues
|
||||||
|
|
||||||
|
**Tests failing with permission errors**
|
||||||
|
|
||||||
|
- Ensure test files have correct permissions
|
||||||
|
- Check that test setup properly grants necessary permissions
|
||||||
|
|
||||||
|
### Performance Issues
|
||||||
|
|
||||||
|
**Slow compile times**
|
||||||
|
|
||||||
|
- Use `cargo check` instead of `cargo build` when possible
|
||||||
|
- Use `--bin deno` to build only the main binary
|
||||||
|
- Use `sccache` or `mold` linker for faster builds
|
||||||
|
- Consider using `cargo-watch` for incremental builds
|
||||||
|
|
||||||
|
### Runtime Debugging
|
||||||
|
|
||||||
|
**Crashes or panics**
|
||||||
|
|
||||||
|
- Run with `RUST_BACKTRACE=1` for full backtrace
|
||||||
|
- Use `RUST_BACKTRACE=full` for even more detail
|
||||||
|
- Check for unwrap() calls that might panic
|
||||||
|
|
||||||
|
**Unexpected behavior**
|
||||||
|
|
||||||
|
- Add debug prints liberally
|
||||||
|
- Use the inspector for JS-side debugging
|
||||||
|
- Check permission grants - many features require explicit permissions
|
||||||
|
|
||||||
|
### Getting Help
|
||||||
|
|
||||||
|
- Check existing issues on GitHub
|
||||||
|
- Look at recent PRs for similar changes
|
||||||
|
- Review the Discord community for discussions
|
||||||
|
- When in doubt, ask! The maintainers are helpful
|
||||||
Loading…
Add table
Add a link
Reference in a new issue