Compare commits
2 Commits
v0.1.3
...
6d4f3eb821
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d4f3eb821 | ||
|
|
e68e4b48f5 |
45
.claude/commands/release.md
Normal file
45
.claude/commands/release.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
Create a new Gitea release for this project using semantic versioning.
|
||||||
|
|
||||||
|
## Current state
|
||||||
|
|
||||||
|
Fetch tags and find the latest version:
|
||||||
|
|
||||||
|
```
|
||||||
|
!git fetch --tags && git tag --sort=-v:refname | head -5
|
||||||
|
```
|
||||||
|
|
||||||
|
Commits since the last release (if no tags exist, this shows all commits):
|
||||||
|
|
||||||
|
```
|
||||||
|
!git log $(git describe --tags --abbrev=0 2>/dev/null && echo "$(git describe --tags --abbrev=0)..HEAD" || echo "") --oneline
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
1. **Determine current version** from the tag output above. If no `vX.Y.Z` tags exist, treat current version as `v0.0.0`.
|
||||||
|
|
||||||
|
2. **Analyze commits** using conventional commit prefixes to pick the semver bump:
|
||||||
|
- Breaking changes (`!` after type, or `BREAKING CHANGE` in body) → **major** bump
|
||||||
|
- `feat:` → **minor** bump
|
||||||
|
- `fix:`, `chore:`, `deps:`, `revert:`, and everything else → **patch** bump
|
||||||
|
- Use the **highest** applicable bump level across all commits
|
||||||
|
|
||||||
|
3. **Generate release notes** — group commits into sections:
|
||||||
|
- **Features** — `feat:` commits
|
||||||
|
- **Fixes** — `fix:` commits
|
||||||
|
- **Other** — everything else (`chore:`, `deps:`, `revert:`, etc.)
|
||||||
|
- Omit empty sections. Each commit is a bullet point with its short description (strip the prefix).
|
||||||
|
|
||||||
|
4. **Present for approval** — show the user:
|
||||||
|
- Current version → proposed new version
|
||||||
|
- The full release notes
|
||||||
|
- The exact `tea` command that will run
|
||||||
|
- Ask the user to confirm before proceeding
|
||||||
|
|
||||||
|
5. **Create the release** — on user approval, run:
|
||||||
|
```
|
||||||
|
tea releases create --login gitea --repo ryan/c4 --tag <version> --target main -t "<version>" -n "<release notes>"
|
||||||
|
```
|
||||||
|
Do NOT create a local git tag — Gitea creates it server-side.
|
||||||
|
|
||||||
|
6. **Verify** — run `tea releases ls --login gitea --repo ryan/c4` to confirm the release was created.
|
||||||
@@ -6,10 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PubSub interface {
|
|
||||||
Publish(subject string, data []byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type PlayerSession struct {
|
type PlayerSession struct {
|
||||||
Player *Player
|
Player *Player
|
||||||
}
|
}
|
||||||
@@ -25,8 +21,8 @@ type Persister interface {
|
|||||||
type GameStore struct {
|
type GameStore struct {
|
||||||
games map[string]*GameInstance
|
games map[string]*GameInstance
|
||||||
gamesMu sync.RWMutex
|
gamesMu sync.RWMutex
|
||||||
persister Persister
|
persister Persister
|
||||||
pubsub PubSub
|
notifyFunc func(gameID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGameStore() *GameStore {
|
func NewGameStore() *GameStore {
|
||||||
@@ -39,14 +35,14 @@ func (gs *GameStore) SetPersister(p Persister) {
|
|||||||
gs.persister = p
|
gs.persister = p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *GameStore) SetPubSub(ps PubSub) {
|
func (gs *GameStore) SetNotifyFunc(f func(gameID string)) {
|
||||||
gs.pubsub = ps
|
gs.notifyFunc = f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gs *GameStore) makeNotify(gameID string) func() {
|
func (gs *GameStore) makeNotify(gameID string) func() {
|
||||||
return func() {
|
return func() {
|
||||||
if gs.pubsub != nil {
|
if gs.notifyFunc != nil {
|
||||||
gs.pubsub.Publish("game."+gameID, nil)
|
gs.notifyFunc(gameID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
main.go
8
main.go
@@ -81,8 +81,12 @@ func main() {
|
|||||||
subFS, _ := fs.Sub(assets, "assets")
|
subFS, _ := fs.Sub(assets, "assets")
|
||||||
v.StaticFS("/assets/", subFS)
|
v.StaticFS("/assets/", subFS)
|
||||||
|
|
||||||
store.SetPubSub(v.PubSub())
|
store.SetNotifyFunc(func(gameID string) {
|
||||||
snakeStore.SetPubSub(v.PubSub())
|
v.PubSub().Publish("game."+gameID, nil)
|
||||||
|
})
|
||||||
|
snakeStore.SetNotifyFunc(func(gameID string) {
|
||||||
|
v.PubSub().Publish("snake."+gameID, nil)
|
||||||
|
})
|
||||||
|
|
||||||
// Home page - tabbed lobby
|
// Home page - tabbed lobby
|
||||||
v.Page("/", func(c *via.Context) {
|
v.Page("/", func(c *via.Context) {
|
||||||
|
|||||||
@@ -6,10 +6,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PubSub interface {
|
|
||||||
Publish(subject string, data []byte) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type Persister interface {
|
type Persister interface {
|
||||||
SaveSnakeGame(sg *SnakeGame) error
|
SaveSnakeGame(sg *SnakeGame) error
|
||||||
LoadSnakeGame(id string) (*SnakeGame, error)
|
LoadSnakeGame(id string) (*SnakeGame, error)
|
||||||
@@ -21,8 +17,8 @@ type Persister interface {
|
|||||||
type SnakeStore struct {
|
type SnakeStore struct {
|
||||||
games map[string]*SnakeGameInstance
|
games map[string]*SnakeGameInstance
|
||||||
gamesMu sync.RWMutex
|
gamesMu sync.RWMutex
|
||||||
persister Persister
|
persister Persister
|
||||||
pubsub PubSub
|
notifyFunc func(gameID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSnakeStore() *SnakeStore {
|
func NewSnakeStore() *SnakeStore {
|
||||||
@@ -35,14 +31,14 @@ func (ss *SnakeStore) SetPersister(p Persister) {
|
|||||||
ss.persister = p
|
ss.persister = p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SnakeStore) SetPubSub(ps PubSub) {
|
func (ss *SnakeStore) SetNotifyFunc(f func(gameID string)) {
|
||||||
ss.pubsub = ps
|
ss.notifyFunc = f
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ss *SnakeStore) makeNotify(gameID string) func() {
|
func (ss *SnakeStore) makeNotify(gameID string) func() {
|
||||||
return func() {
|
return func() {
|
||||||
if ss.pubsub != nil {
|
if ss.notifyFunc != nil {
|
||||||
ss.pubsub.Publish("snake."+gameID, nil)
|
ss.notifyFunc(gameID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user