[teamai] Push 87 resource(s) from XingfenD

This commit is contained in:
2026-09-10 16:10:45 +08:00
parent 425c9c078a
commit 65c04def51
1314 changed files with 211681 additions and 0 deletions
@@ -0,0 +1,210 @@
# Application Documentation
→ See `samber/cc-skills-golang@golang-cli` skill for CLI application patterns and frameworks.
## CLI Help Text
For CLI applications, `--help` output is the primary documentation. CLI tools MUST have comprehensive `--help` text:
```go
// Use cobra or similar framework for structured help text
var rootCmd = &cobra.Command{
Use: "mytool",
Short: "A brief description of mytool",
Long: `A longer description that explains the tool in detail.
mytool helps you do X, Y, and Z. It connects to your
database and performs analysis on the data.
Environment variables:
MYTOOL_DB_URL Database connection string (required)
MYTOOL_LOG_LEVEL Log level: debug, info, warn, error (default: info)
MYTOOL_TIMEOUT Request timeout (default: 30s)`,
Example: ` # Basic usage
mytool analyze --input data.csv
# With custom configuration
mytool analyze --input data.csv --output report.json --format json
# Using environment variables
export MYTOOL_DB_URL="postgres://localhost/mydb"
mytool serve`,
}
```
---
## Configuration Documentation
Configuration SHOULD be documented. Document all configuration sources in the README or a dedicated `docs/configuration.md`:
````markdown
## Configuration
Configuration is loaded in this order (later sources override earlier ones):
1. Default values
2. Configuration file (`~/.config/mytool/config.yaml`)
3. Environment variables
4. Command-line flags
### Environment Variables
| Variable | Description | Default | Required |
| ------------------ | -------------------------- | ------- | -------- |
| `MYTOOL_DB_URL` | Database connection string | — | Yes |
| `MYTOOL_LOG_LEVEL` | Log verbosity | `info` | No |
| `MYTOOL_PORT` | HTTP server port | `8080` | No |
| `MYTOOL_TIMEOUT` | Request timeout | `30s` | No |
### Configuration File
```yaml
# ~/.config/mytool/config.yaml
database:
url: postgres://localhost/mydb
max_connections: 25
server:
port: 8080
read_timeout: 30s
logging:
level: info
format: json
```
````
---
## Architecture & design decisions
For complex applications, document architectural decisions in `docs/architecture/`:
```
docs/
architecture/
0001-use-postgres-as-primary-store.md
0002-event-driven-architecture.md
0003-jwt-for-authentication.md
README.md
```
Each design document follows a standard format:
```markdown
# Use PostgreSQL as Primary Store
## Context
We need a persistent data store that supports...
## Design
We use PostgreSQL because...
## Consequences
- Positive: ACID transactions, rich query language...
- Negative: Operational overhead, connection management...
```
---
## API Documentation
### REST APIs — OpenAPI / Swagger
Use [swaggo/swag](https://github.com/swaggo/swag) to auto-generate OpenAPI docs from Go annotations:
```go
// @Summary Get user by ID
// @Description Returns a single user
// @Tags users
// @Accept json
// @Produce json
// @Param id path int true "User ID"
// @Success 200 {object} User
// @Failure 404 {object} ErrorResponse
// @Failure 500 {object} ErrorResponse
// @Router /users/{id} [get]
func GetUser(w http.ResponseWriter, r *http.Request) {
```
Generate the spec:
```bash
go get -tool github.com/swaggo/swag/cmd/swag@latest
go tool swag init -g cmd/server/main.go -o docs/swagger
```
This produces `docs/swagger/swagger.json` and `docs/swagger/swagger.yaml`. Serve with Swagger UI or Redoc.
### Event-Driven — AsyncAPI
For message-based APIs (Kafka, NATS, RabbitMQ), use [AsyncAPI](https://www.asyncapi.com/):
```yaml
asyncapi: "2.6.0"
info:
title: Order Events
version: "1.0.0"
channels:
orders/created:
publish:
message:
payload:
type: object
properties:
orderId:
type: string
amount:
type: number
```
### gRPC — Protobuf
Protobuf files serve as both code contracts and documentation. Add comments to messages and RPCs:
```protobuf
syntax = "proto3";
// UserService manages user accounts.
service UserService {
// GetUser retrieves a user by their unique identifier.
// Returns NOT_FOUND if the user does not exist.
rpc GetUser(GetUserRequest) returns (User);
// CreateUser registers a new user account.
// Returns ALREADY_EXISTS if the email is taken.
rpc CreateUser(CreateUserRequest) returns (User);
}
// User represents a registered user account.
message User {
// Unique identifier for the user (UUID v4).
string id = 1;
// User's display name (1-100 characters).
string name = 2;
// User's email address (must be unique across all users).
string email = 3;
}
```
Use [buf](https://buf.build/) for linting and breaking change detection:
```bash
buf lint
buf breaking --against '.git#branch=main'
```
For REST+gRPC, use [grpc-gateway](https://github.com/grpc-ecosystem/grpc-gateway) to serve both from the same protobuf definition.
### When to Use Each Format
| API Style | Format | Auto-generation |
| --- | --- | --- |
| REST/HTTP with Go handlers | OpenAPI 3.x | swaggo/swag from annotations |
| REST/HTTP with framework | OpenAPI 3.x | Framework-specific (e.g., huma) |
| gRPC services | Protobuf | Proto files are the source of truth |
| gRPC + REST gateway | Protobuf + OpenAPI | grpc-gateway generates OpenAPI |
| Message queues / events | AsyncAPI | Manual or code-gen |
| GraphQL | SDL schema | Schema is the docs |
@@ -0,0 +1,329 @@
# Code Comments
→ See `samber/cc-skills-golang@golang-naming` skill for naming conventions that reduce the need for comments.
## Function & Method Doc Comments
### Why, Not What
The most common mistake in doc comments is restating the code. The code already tells the reader _what_ happens — comments SHOULD explain why, not what:
- **Why** this function exists (its purpose in the system)
- **When** to use it (and when not to)
- **What constraints** apply (preconditions, thread safety, performance)
- **What can go wrong** (error cases, panics, edge cases)
Bad — restates the code:
```go
// GetUser gets a user by ID.
func GetUser(id string) (*User, error) {
```
Good — explains why, when, and what can go wrong:
```go
// GetUser retrieves a user from the database by their unique identifier.
// Use this for authenticated endpoints where you need the full user profile.
// For listing or searching, use ListUsers instead — it returns lighter projections.
//
// Returns ErrNotFound if no user exists with the given ID.
// Returns ErrDatabaseUnavailable if the connection pool is exhausted.
func GetUser(id string) (*User, error) {
```
### Anti-Patterns to Remove on Sight
| Anti-pattern | Example | Fix |
| --- | --- | --- |
| Pure paraphrase | `// GetUser gets a user` on `func GetUser()` — starts with the name (required by godoc) but adds nothing | After the name, add _when_ to use it, constraints, and what can go wrong |
| Signature restatement | `// Returns a string and an error` | Document _which_ error and _why_ — the signature already shows types |
| Marketing vocabulary | `seamlessly`, `powerful`, `robust`, `enterprise-grade` | Remove — state facts instead |
| Invented rationale | `// designed to improve scalability` | Only document what the code actually does |
| Groundless future claims | `// supports future extensibility` | Remove or back it with an interface or configuration |
| Hollow filler | `// It's worth noting that...`, `// As mentioned above` | Cut — restate the fact directly if it matters |
### Format
Every doc comment MUST start with the function/method name followed by a verb phrase. This is how godoc renders it in package indexes.
```go
// FuncName verb-phrase describing what it does.
```
### Full Comment Template
Use this structure for exported functions and complex internal functions. Omit sections that don't apply (e.g., no Parameters section for zero-arg functions). Focus on the "why" — don't restate what the code already makes obvious:
```go
// FuncName summarizes what this function does in one sentence.
// Additional context explaining behavior, algorithms, or design decisions
// that callers need to know.
//
// Parameters:
// - paramName: description of what this parameter represents
// - anotherParam: description with valid ranges or constraints
//
// Returns description of the return value(s).
// Returns ErrSomething if [condition].
// Returns ErrAnother if [different condition].
//
// Panics if [condition] (only document if the function can panic).
//
// It is safe for concurrent use (or: It is NOT safe for concurrent use).
//
// Play: https://go.dev/play/p/xxxxx
//
// Example:
//
// result, err := pkg.FuncName(arg1, arg2)
// if err != nil {
// log.Fatal(err)
// }
// fmt.Println(result)
func FuncName(paramName Type, anotherParam Type) (ResultType, error) {
```
### What to Document
| Element | Document? |
| --- | --- |
| Exported functions/methods | Always |
| Exported types and interfaces | Always |
| Exported constants and variables | Always |
| Complex internal functions | Yes — algorithms, non-obvious logic |
| Simple internal helpers | Optional — only if the name isn't self-explanatory |
| Test functions | No |
| Getters/setters with no logic | Brief one-liner is enough |
`TODO` comments SHOULD include a tracking issue reference when one exists (e.g., `// TODO(#123): ...`). For informal notes, `// TODO(username): ...` or plain `// TODO: ...` is acceptable.
### Error Cases and Limitations
Document every error a function can return, and any edge cases or limitations:
```go
// Parse parses a duration string such as "300ms", "1.5h", or "2h45m".
//
// Parameters:
// - s: A duration string. Valid time units are "ns", "us", "ms", "s", "m", "h".
//
// Returns the parsed duration.
// Returns ErrInvalidDuration if the string is empty or has an invalid format.
// Returns ErrOverflow if the duration exceeds math.MaxInt64 nanoseconds.
//
// Limitations:
// - Does not support day, week, month, or year units.
// - Precision is limited to nanoseconds.
func Parse(s string) (time.Duration, error) {
```
### Deprecated Functions
Use the `Deprecated:` marker. godoc renders this with special styling:
```go
// OldFunc does something.
//
// Deprecated: Use NewFunc instead. OldFunc will be removed in v3.0.0.
func OldFunc() {}
```
### Interface Documentation
Document the interface itself and each method. Explain the contract that implementations must satisfy:
```go
// Store defines a persistent key-value storage backend.
// Implementations must be safe for concurrent use by multiple goroutines.
//
// All methods accept a context for cancellation and deadlines.
// Implementations should respect context cancellation and return
// ctx.Err() when the context is done.
type Store interface {
// Get retrieves the value associated with key.
// Returns ErrNotFound if the key does not exist.
// Returns ErrExpired if the key exists but has expired.
Get(ctx context.Context, key string) ([]byte, error)
// Set stores a key-value pair with an optional TTL.
// If ttl is 0, the entry does not expire.
// Overwrites any existing value for the same key.
Set(ctx context.Context, key string, value []byte, ttl time.Duration) error
// Delete removes a key from the store.
// Returns nil (not an error) if the key does not exist.
Delete(ctx context.Context, key string) error
}
```
### Method Comments on Structs
```go
// Close gracefully shuts down the server.
// It waits for active connections to complete up to the configured timeout.
//
// Returns an error if the shutdown times out or if the server
// encounters an error while draining connections.
//
// Close is idempotent — calling it multiple times is safe.
// It is NOT safe to call Close concurrently from multiple goroutines.
func (s *Server) Close() error {
```
### Inline Code Examples in Comments
Indent code examples by one tab in doc comments. godoc renders these as formatted code blocks:
```go
// Transform applies a function to each element of a slice and returns
// a new slice with the results.
//
// Example:
//
// names := []string{"alice", "bob"}
// upper := Transform(names, strings.ToUpper)
// // upper: ["ALICE", "BOB"]
func Transform[T any, U any](slice []T, fn func(T) U) []U {
```
### Playground Links
Add a `Play:` line linking to a runnable Go Playground example of a public library. Use the samber/go-playground-mcp tool to create and share playground URLs when available:
```go
// Map applies a function to each element of a slice.
//
// Play: https://go.dev/play/p/abc123xyz
//
// Example:
//
// doubled := Map([]int{1, 2, 3}, func(x int) int { return x * 2 })
// // doubled: [2, 4, 6]
func Map[T any, U any](s []T, fn func(T) U) []U {
```
---
## File & Package Comments
### Package Comment
Every package should have a doc comment. Place it in one of these locations:
1. **At the top of the main `.go` file** — for small packages with one or two files
2. **In a dedicated `doc.go` file** — for packages with many files
```go
// Package httputil provides HTTP utility functions for request parsing,
// response writing, and middleware chaining.
//
// It is designed to work with the standard net/http package and does not
// depend on any specific HTTP framework.
package httputil
```
Use `doc.go` when the package has 3+ files or the package comment is longer than ~10 lines:
```go
// Package auth implements authentication and authorization for the API server.
//
// # Architecture
//
// The package uses a middleware-based approach where each authentication
// strategy (JWT, API key, OAuth2) implements the Authenticator interface.
// Strategies are chained and tried in order until one succeeds.
//
// # Token Lifecycle
//
// Access tokens expire after 15 minutes. Refresh tokens expire after 7 days.
// Token rotation is automatic — each refresh request issues a new refresh token
// and invalidates the previous one.
//
// # Thread Safety
//
// All exported functions and types are safe for concurrent use.
package auth
```
### File-Level Description
For files that implement a specific algorithm, feature, or contain complex logic, add a descriptive comment block below the imports. This is a macro description — explain **why** this file or package exists, what problem it solves, and what design choices were made. Use ASCII art to describe complex flows or architectures. Don't describe what each line does:
```go
package scheduler
import (
"container/heap"
"sync"
"time"
)
// This file implements a priority-queue-based task scheduler.
//
// Tasks are scheduled with a target execution time and stored in a min-heap
// ordered by deadline. A single dispatcher goroutine polls the heap and
// executes tasks when their deadline arrives.
//
// Supports: recurring tasks, one-shot tasks, task cancellation, and
// graceful shutdown with drain timeout.
//
// Architecture:
//
// Schedule(task)
// |
// v
// [Min-Heap Queue]
// (by deadline)
// |
// Dispatcher Goroutine
// (polling loop)
// / \
// / \
// Deadline Deadline
// not reached reached
// | |
// wait v
// Execute
// |
// Recurring? | One-shot
// / | \
// / v \
// Re-queue Complete Discard
// \ | /
// \ | /
// v v v
// [Continue polling]
type Scheduler struct {
```
### When to Add File Descriptions
| Scenario | Add description? |
| --- | --- |
| File implements an algorithm (sorting, scheduling, tree traversal) | Yes |
| File contains a complex state machine or protocol | Yes |
| File has 200+ lines of related logic | Yes |
| File is a simple CRUD handler or data model | No |
| File name already explains everything (`json_parser.go`) | Only if non-obvious |
### Godoc Headings in Comments
Use `# Heading` syntax in doc comments (Go 1.19+) for structured documentation:
```go
// Package config provides configuration loading and validation.
//
// # Supported Sources
//
// Configuration can be loaded from environment variables, YAML files,
// or command-line flags. Sources are merged in order of precedence:
// flags > env vars > config file > defaults.
//
// # Validation
//
// All configuration values are validated at load time. Invalid values
// cause an immediate error rather than failing later at runtime.
package config
```
@@ -0,0 +1,197 @@
# Library Documentation
→ See `samber/cc-skills-golang@golang-testing` skill for writing effective Example test functions.
## Public vs Private Libraries
Not all documentation applies equally. Adapt to your audience:
| Documentation | Public Library | Private Library |
| --- | --- | --- |
| Doc comments on exported symbols | Required | Required |
| Package comments | Required | Required |
| README.md | Required | Required |
| Code examples in comments | Generous | Generous |
| `ExampleXxx()` test functions | Recommended | Recommended |
| Go Playground demos | Recommended | N/A (code not public) |
| pkg.go.dev / godoc | Primary docs surface | Use `go doc` locally or internal tooling |
| Documentation website | Large projects | Only if many teams consume the library |
| Register in Context7/DeepWiki/etc. | Recommended | N/A |
| llms.txt | Recommended | Optional |
| CHANGELOG.md | Recommended | Recommended |
| CONTRIBUTING.md | Recommended | Recommended (internal wiki may suffice) |
**Private libraries** should still have excellent doc comments and examples — teams rotate, people forget, and AI agents need context to help effectively. The main difference is you skip public-facing artifacts (playground, pkg.go.dev, registries).
---
## Go Playground Demos
Create runnable demos on the Go Playground and link them in doc comments. This lets users try your library without installing anything. Only applicable to public libraries.
Add a `Play:` line in the doc comment:
```go
// Map applies fn to each element of the slice and returns a new slice.
//
// Play: https://go.dev/play/p/abc123xyz
//
// Example:
//
// doubled := Map([]int{1, 2, 3}, func(x int) int { return x * 2 })
// // doubled: [2, 4, 6]
func Map[T any, U any](s []T, fn func(T) U) []U {
```
When the samber/go-playground-mcp tool is available, use it to create and share playground URLs. Otherwise, create them manually at <https://go.dev/play/>.
Guidelines for playground demos:
- Keep demos self-contained — include all imports and a `main()` function
- Show the most common use case first
- Show real-world examples
- Print results so the output is visible when someone clicks "Run"
- Add comments explaining what each section does
---
## Example Test Functions
Libraries MUST have Example test functions for exported APIs. Example functions are executable documentation. They appear in godoc and are verified by `go test`:
```go
// In map_example_test.go
package mypackage_test
import (
"fmt"
"github.com/{owner}/{repo}"
)
// ExampleMap demonstrates mapping over a slice.
func ExampleMap() {
result := mypackage.Map([]int{1, 2, 3}, func(x int) int {
return x * 2
})
fmt.Println(result)
// Output: [2 4 6]
}
// ExampleMap_strings demonstrates mapping with string transformation.
func ExampleMap_strings() {
result := mypackage.Map([]string{"hello", "world"}, strings.ToUpper)
fmt.Println(result)
// Output: [HELLO WORLD]
}
```
Naming conventions:
- `ExampleFuncName()` — example for a package-level function
- `ExampleTypeName()` — example for a type
- `ExampleTypeName_MethodName()` — example for a method
- `ExampleFuncName_suffix()` — multiple examples for the same function (suffix is lowercase)
- `Example()` — example for the whole package
The `// Output:` comment MUST be included for `go test` to verify the example. Without it, the example compiles but doesn't verify output.
---
## Code Examples in Doc Comments
Be generous with examples in doc comments. Show common use cases, edge cases, and error handling:
```go
// NewClient creates a new HTTP client with the given options.
//
// Example — basic client:
//
// client := NewClient()
//
// Example — with custom timeout and retries:
//
// client := NewClient(
// WithTimeout(10 * time.Second),
// WithRetries(3),
// WithRetryBackoff(time.Second),
// )
//
// Example — with authentication:
//
// client := NewClient(
// WithBearerToken(os.Getenv("API_TOKEN")),
// )
func NewClient(opts ...Option) *Client {
```
---
## godoc and pkg.go.dev
Your doc comments automatically render on [pkg.go.dev](https://pkg.go.dev) when you tag a release and someone imports your package. This is the primary documentation surface for public Go libraries.
**How godoc renders comments:**
- First sentence of each doc comment appears in the package index
- `// Package foo provides...` appears as the package description
- Code blocks (indented by one tab) render as formatted code
- `# Heading` syntax (Go 1.19+) creates sections
- `[Link text]` syntax creates hyperlinks
- `[Identifier]` links to other symbols in the package
- `Deprecated:` marker gets special styling
**For private libraries:** pkg.go.dev won't index private modules. Use `go doc` locally or run `pkgsite` on your internal network. Some teams set up a shared pkgsite instance for internal Go modules.
```bash
# View docs for a specific symbol
go doc github.com/{owner}/{repo}.FuncName
# View full package docs
go doc -all github.com/{owner}/{repo}
# Start a local godoc server
go get -tool golang.org/x/pkgsite/cmd/pkgsite@latest
go tool pkgsite -http=:6060
# Then open http://localhost:6060
```
---
## Documentation Website
For larger libraries or frameworks, consider a dedicated documentation website.
### Recommended Frameworks
- **Docusaurus** (React-based) — best for large projects, supports versioning natively
- **MkDocs Material** (Python-based) — simpler setup, great search, clean design
Both can be deployed on Vercel.
### Recommended Sections
Follow the [Diataxis framework](https://diataxis.fr/) for organizing documentation:
| Section | Purpose | Example |
| --- | --- | --- |
| Getting Started | First steps, installation, hello world | "Install and run your first query in 5 minutes" |
| Tutorial | Step-by-step learning | "Build a REST API with authentication" |
| How-to Guides | Task-oriented recipes | "How to configure connection pooling" |
| Reference | Complete API documentation | Auto-generated from godoc |
| Deep dive / internals | Conceptual understanding | "How the scheduler algorithm works" |
### llms.txt
Add a `llms.txt` file at the repository root to help AI agents understand your project. Copy the template from [templates/llms.txt](./templates/llms.txt).
This is an emerging convention for making projects AI-friendly. Place it alongside your README.
### Register for Discoverability
Make your library findable by AI agents and documentation aggregators:
- **Context7** — <https://context7.com> — submit your library for inclusion in AI-accessible documentation
- **DeepWiki** — <https://deepwiki.com> — auto-generates wiki-style docs from GitHub repos
- **OpenDeep** — <https://opendeep.wiki> — open documentation platform for AI consumption
- **zRead** — <https://zread.ai> — developer documentation reader
@@ -0,0 +1,115 @@
# Project Documentation
→ See `samber/cc-skills-golang@golang-continuous-integration` skill for automating changelog generation and release workflows.
## README.md
A LICENSE file MUST exist in every project. A README is the front page of your project. Make it simple, clear, and scannable. A copy-paste template with empty sections is available at [templates/README.md](./templates/README.md).
### Section Order
Follow this exact order (all sections are in the template):
1. **Title** — project name as `# heading`
2. **Badges** — shields.io pictograms (Go version, license, CI, coverage, Go Report Card)
3. **Summary** — 1-2 sentences explaining what the project does
4. **Demo** — code snippet (libraries), GIF/video (CLIs), or screenshot (web UIs)
5. **Getting Started** — installation + minimal working example
6. **Features / Specification** — the longest section, organized by feature area
7. **Contributing** — link to CONTRIBUTING.md or inline if very short
8. **License** — license name + link
The template includes commented-out sections for applications (binary download table, Docker, Homebrew) that you can uncomment as needed.
---
## CONTRIBUTING.md
The goal: a new contributor should be able to clone the repo, make a change, and run the tests **in under 10 minutes**. If your project takes longer, add tooling to fix that.
Copy the template from [templates/CONTRIBUTING.md](./templates/CONTRIBUTING.md).
### The 10-Minute Rule
If setup takes more than 10 minutes, add these improvements:
| Problem | Solution |
| --- | --- |
| Complex build steps | Add a `Makefile` with `make build`, `make test`, `make lint` |
| External service dependencies | Add `docker-compose.yml` for local dev |
| Inconsistent dev environments | Add `.devcontainer/` for VS Code devcontainers |
| Slow test suite | Separate unit tests (fast) from integration tests (build tags) |
| Missing documentation | Add `make help` that lists available targets |
---
## Changelog
CHANGELOG MUST be updated for every release. Track notable changes for each release. Use [Keep a Changelog](https://keepachangelog.com/) format. Copy the template from [templates/CHANGELOG.md](./templates/CHANGELOG.md).
### Format
```markdown
## [1.2.0] - 2026-03-08
### Added
- New `WithTimeout` option for client configuration
### Changed
- Improved retry logic to use exponential backoff
### Fixed
- Race condition in connection pool under heavy load
### Deprecated
- `SetTimeout()` method — use `WithTimeout()` option instead
[1.2.0]: https://github.com/{owner}/{repo}/compare/v1.1.0...v1.2.0
```
### Change Categories
- **Added** — new features
- **Changed** — changes in existing functionality
- **Deprecated** — features that will be removed
- **Removed** — removed features
- **Fixed** — bug fixes
- **Security** — vulnerability fixes
### GitHub Releases as Alternative
For simpler projects, GitHub Releases can replace a CHANGELOG file. GoReleaser auto-generates release notes from git commits.
---
## Distribution
**YOU MUST offer multiple installation paths** (binaries, containers, APT/Homebrew/... package managers, source). Because:
- Each installation method eliminates friction for a different user segment
- Users adopt tools that fit their workflow, not tools that force workflow changes
- A single installation path is a hidden tax on adoption—DevOps engineers skip tools requiring npm, macOS developers skip tools without Homebrew
- Tools users _want to_ use spread faster than tools users _have to_ accommodate
### Dockerfile Best Practices
Use multi-stage builds with a minimal final image:
```dockerfile
# Build stage
FROM golang:1.26-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags="-s -w" -o /app/binary ./cmd/server
# Final stage
FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=builder /app/binary /binary
ENTRYPOINT ["/binary"]
```