Establish initial Go application skeleton
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,5 @@
|
||||
# Compiled application binary
|
||||
weatherreporter
|
||||
/weatherreporter
|
||||
|
||||
# ---> Go
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
@@ -71,4 +71,3 @@ Icon
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
|
||||
20
README.md
20
README.md
@@ -1,2 +1,22 @@
|
||||
# weatherreporter
|
||||
|
||||
`weatherreporter` is a Go application for preparing human-facing weather
|
||||
reports from normalized forecast data.
|
||||
|
||||
The repository currently contains the application skeleton and a minimal CLI
|
||||
help command. Report generation, configuration loading, weather API fetching,
|
||||
and `scriptorium` rendering are tracked in the roadmap and are not implemented
|
||||
yet.
|
||||
|
||||
## Quickstart
|
||||
|
||||
```sh
|
||||
weatherreporter --help
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
- [CLI reference](docs/cli.md)
|
||||
- [Architecture policy](docs/policy/architecture.md)
|
||||
- [Development policy](docs/policy/development.md)
|
||||
- [Implementation roadmap](docs/roadmap/initial.md)
|
||||
|
||||
16
cmd/weatherreporter/main.go
Normal file
16
cmd/weatherreporter/main.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gitea.maximumdirect.net/eric/weatherreporter/internal/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := cli.Run(context.Background(), os.Args[1:], os.Stdout, os.Stderr); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "weatherreporter: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
23
docs/cli.md
Normal file
23
docs/cli.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Weatherreporter CLI
|
||||
|
||||
`weatherreporter` currently exposes only the root help command while the
|
||||
application skeleton is being established.
|
||||
|
||||
## Shortest Useful Command
|
||||
|
||||
```sh
|
||||
weatherreporter --help
|
||||
```
|
||||
|
||||
## Command Overview
|
||||
|
||||
```text
|
||||
weatherreporter --help
|
||||
```
|
||||
|
||||
Shows the available command-line help without loading configuration or calling
|
||||
external services.
|
||||
|
||||
## Flags
|
||||
|
||||
- `-h`, `--help`: show help.
|
||||
3
go.mod
Normal file
3
go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module gitea.maximumdirect.net/eric/weatherreporter
|
||||
|
||||
go 1.26
|
||||
2
internal/app/doc.go
Normal file
2
internal/app/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package app owns application orchestration and top-level use cases.
|
||||
package app
|
||||
45
internal/cli/root.go
Normal file
45
internal/cli/root.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
const helpText = `weatherreporter prepares weather reports from normalized forecast data.
|
||||
|
||||
Usage:
|
||||
weatherreporter --help
|
||||
|
||||
Options:
|
||||
-h, --help Show this help message.
|
||||
`
|
||||
|
||||
// Run parses the root command and executes the selected behavior.
|
||||
func Run(ctx context.Context, args []string, stdout io.Writer, stderr io.Writer) error {
|
||||
_ = ctx
|
||||
_ = stderr
|
||||
|
||||
fs := flag.NewFlagSet("weatherreporter", flag.ContinueOnError)
|
||||
fs.SetOutput(io.Discard)
|
||||
|
||||
help := fs.Bool("help", false, "show help")
|
||||
fs.BoolVar(help, "h", false, "show help")
|
||||
|
||||
if err := fs.Parse(args); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if *help {
|
||||
_, err := fmt.Fprint(stdout, helpText)
|
||||
return err
|
||||
}
|
||||
|
||||
if fs.NArg() > 0 {
|
||||
return fmt.Errorf("unknown argument %q", fs.Arg(0))
|
||||
}
|
||||
|
||||
_, err := fmt.Fprint(stdout, helpText)
|
||||
return err
|
||||
}
|
||||
50
internal/cli/root_test.go
Normal file
50
internal/cli/root_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRunHelpLongFlag(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
err := Run(context.Background(), []string{"--help"}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(stdout.String(), "Usage:") {
|
||||
t.Fatalf("help output missing usage:\n%s", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunHelpShortFlag(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
err := Run(context.Background(), []string{"-h"}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
|
||||
if !strings.Contains(stdout.String(), "weatherreporter --help") {
|
||||
t.Fatalf("help output missing root help command:\n%s", stdout.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunUnknownArgument(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
err := Run(context.Background(), []string{"generate"}, &stdout, &stderr)
|
||||
if err == nil {
|
||||
t.Fatal("Run() error = nil, want unknown argument error")
|
||||
}
|
||||
|
||||
if !strings.Contains(err.Error(), `unknown argument "generate"`) {
|
||||
t.Fatalf("Run() error = %q, want unknown argument message", err.Error())
|
||||
}
|
||||
}
|
||||
3
internal/config/doc.go
Normal file
3
internal/config/doc.go
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package config owns application configuration structures, defaults, loading,
|
||||
// precedence, and validation.
|
||||
package config
|
||||
Reference in New Issue
Block a user