Split phrase list out into community-editable phrases.yaml
Some checks are pending
CI / test (push) Waiting to run
Some checks are pending
CI / test (push) Waiting to run
config.yaml previously mixed secrets with the phrase list, forcing private-only edits. Now config supports phrases_file, which is loaded and merged with any private phrases: entries, so the repo-tracked phrases.yaml can be extended via PR while per-deployment additions stay private. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
6e023d1081
commit
f411886d88
5 changed files with 115 additions and 25 deletions
|
|
@ -27,7 +27,9 @@ Forgejo上にbot専用アカウント(例: `yaju-keisatsu-bot`)を作り、そ
|
|||
cp config.example.yaml config.yaml
|
||||
```
|
||||
|
||||
`config.yaml` を編集し、`forgejo.base_url` / `forgejo.token` / `webhook_secret` / `bot.username` を埋める。`phrases` は同梱の一部だけなので、必要に応じて自分の `config.yaml` に自由に追加してよい(このリストは本体の意図的にライトな内容にとどめてあります)。
|
||||
`config.yaml` を編集し、`forgejo.base_url` / `forgejo.token` / `webhook_secret` / `bot.username` を埋める。
|
||||
|
||||
語録リストは [phrases.yaml](./phrases.yaml) にコミュニティ管理のものが同梱されており、`config.yaml` の `phrases_file: ./phrases.yaml` で読み込む(デフォルトで設定済み)。追加・削除の提案はPRで歓迎。自分の運用だけで使いたい追加語録があれば、それとは別に `config.yaml` の `phrases:` に書けば `phrases_file` の内容とマージされる。
|
||||
|
||||
`config.yaml` は秘密情報を含むため絶対にコミットしないこと(`.gitignore` 済み)。
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# goroku-keisatsu の設定ファイル例。
|
||||
# yaju-is-always-watching-you の設定ファイル例。
|
||||
# コピーして config.yaml として使う。秘密情報が入るので config.yaml は絶対にコミットしないこと。
|
||||
|
||||
listen_addr: ":8080"
|
||||
|
|
@ -11,13 +11,13 @@ forgejo:
|
|||
# 自ホストのForgejoのベースURL
|
||||
base_url: "https://git.example.dev"
|
||||
# bot専用アカウントで発行したAPIトークン(Settings > Applications)。
|
||||
# 権限は対象リポジトリへの read/write + issue + pull-request で十分。
|
||||
# スコープは repository(write) + issue(write) で十分。
|
||||
token: "change-me"
|
||||
|
||||
bot:
|
||||
# 上のtokenを発行したbotアカウントのユーザー名。
|
||||
# このアカウント自身の発言/pushには反応しない(無限ループ防止)。
|
||||
username: "goroku-keisatsu-bot"
|
||||
username: "yaju-keisatsu-bot"
|
||||
# 是正PR用に作成するブランチの接頭辞。
|
||||
branch_prefix: "bot/goroku-fix/"
|
||||
# push時にスキャンする対象拡張子。空にすると全ファイルを対象にする。
|
||||
|
|
@ -29,18 +29,10 @@ bot:
|
|||
- ".js"
|
||||
- ".ts"
|
||||
|
||||
# 検知する語録リスト。有名どころの一部だけを同梱しているので、
|
||||
# 必要に応じて自分のconfig.yamlで自由に追加・削除すること。
|
||||
phrases:
|
||||
- "しょうもな"
|
||||
- "たまげたなあ"
|
||||
- "変態糞土方"
|
||||
- "絶対に許さない"
|
||||
- "24時間戦えますか"
|
||||
- "本当に感謝しております"
|
||||
- "巨大感謝"
|
||||
- "覚悟はいいか?俺はできてる"
|
||||
- "もうだめだ"
|
||||
- "ンアッー"
|
||||
- "ファッ!?"
|
||||
- "24時間タタカエマスカ"
|
||||
# phrases_file: リポジトリ同梱のコミュニティ管理語録リスト(phrases.yaml)を読む。
|
||||
# 相対パスはこのconfig.yamlからの相対で解決される。
|
||||
phrases_file: "./phrases.yaml"
|
||||
|
||||
# phrases: 自分の運用だけで使いたい追加語録があればここに書く(phrases_fileの内容とマージされる)。
|
||||
# 空のままでもOK。
|
||||
phrases: []
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ package config
|
|||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
|
@ -13,6 +14,14 @@ type Config struct {
|
|||
WebhookSecret string `yaml:"webhook_secret"`
|
||||
Forgejo Forgejo `yaml:"forgejo"`
|
||||
Bot Bot `yaml:"bot"`
|
||||
// PhrasesFile, if set, is loaded and merged with Phrases. It lets a
|
||||
// deployment point at the repo's community-maintained phrases.yaml while
|
||||
// still keeping any private additions inline below.
|
||||
PhrasesFile string `yaml:"phrases_file"`
|
||||
Phrases []string `yaml:"phrases"`
|
||||
}
|
||||
|
||||
type phrasesFile struct {
|
||||
Phrases []string `yaml:"phrases"`
|
||||
}
|
||||
|
||||
|
|
@ -48,6 +57,22 @@ func Load(path string) (*Config, error) {
|
|||
return nil, fmt.Errorf("parse config: %w", err)
|
||||
}
|
||||
|
||||
if cfg.PhrasesFile != "" {
|
||||
fp := cfg.PhrasesFile
|
||||
if !filepath.IsAbs(fp) {
|
||||
fp = filepath.Join(filepath.Dir(path), fp)
|
||||
}
|
||||
data, err := os.ReadFile(fp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read phrases_file: %w", err)
|
||||
}
|
||||
var pf phrasesFile
|
||||
if err := yaml.Unmarshal(data, &pf); err != nil {
|
||||
return nil, fmt.Errorf("parse phrases_file: %w", err)
|
||||
}
|
||||
cfg.Phrases = append(pf.Phrases, cfg.Phrases...)
|
||||
}
|
||||
|
||||
if cfg.Forgejo.BaseURL == "" {
|
||||
return nil, fmt.Errorf("forgejo.base_url is required")
|
||||
}
|
||||
|
|
@ -58,7 +83,7 @@ func Load(path string) (*Config, error) {
|
|||
return nil, fmt.Errorf("webhook_secret is required")
|
||||
}
|
||||
if len(cfg.Phrases) == 0 {
|
||||
return nil, fmt.Errorf("phrases list is empty")
|
||||
return nil, fmt.Errorf("phrases list is empty (set phrases and/or phrases_file)")
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
|
|
|
|||
55
internal/config/config_test.go
Normal file
55
internal/config/config_test.go
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func writeFile(t *testing.T, path, content string) {
|
||||
t.Helper()
|
||||
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||
t.Fatalf("write %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad_PhrasesFileMergesWithInline(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
writeFile(t, filepath.Join(dir, "phrases.yaml"), "phrases:\n - しょうもな\n - たまげたなあ\n")
|
||||
writeFile(t, filepath.Join(dir, "config.yaml"), `
|
||||
listen_addr: ":8080"
|
||||
webhook_secret: "s"
|
||||
forgejo:
|
||||
base_url: "http://forgejo:3000"
|
||||
token: "t"
|
||||
phrases_file: "./phrases.yaml"
|
||||
phrases:
|
||||
- 独自の追加語録
|
||||
`)
|
||||
|
||||
cfg, err := Load(filepath.Join(dir, "config.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("Load() error = %v", err)
|
||||
}
|
||||
|
||||
want := []string{"しょうもな", "たまげたなあ", "独自の追加語録"}
|
||||
if !reflect.DeepEqual(cfg.Phrases, want) {
|
||||
t.Fatalf("Phrases = %v, want %v", cfg.Phrases, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoad_MissingPhrasesIsError(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
writeFile(t, filepath.Join(dir, "config.yaml"), `
|
||||
webhook_secret: "s"
|
||||
forgejo:
|
||||
base_url: "http://forgejo:3000"
|
||||
token: "t"
|
||||
`)
|
||||
|
||||
if _, err := Load(filepath.Join(dir, "config.yaml")); err == nil {
|
||||
t.Fatal("Load() error = nil, want error for empty phrases")
|
||||
}
|
||||
}
|
||||
16
phrases.yaml
Normal file
16
phrases.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# コミュニティ管理の語録リスト(誰でもPRで追加・削除を提案してOK)。
|
||||
# 個人の運用固有の追加語録は、この場所ではなく各自の config.yaml の
|
||||
# `phrases:` に書くこと(config.yaml はコミットされないので分離される)。
|
||||
phrases:
|
||||
- "しょうもな"
|
||||
- "たまげたなあ"
|
||||
- "変態糞土方"
|
||||
- "絶対に許さない"
|
||||
- "24時間戦えますか"
|
||||
- "本当に感謝しております"
|
||||
- "巨大感謝"
|
||||
- "覚悟はいいか?俺はできてる"
|
||||
- "もうだめだ"
|
||||
- "ンアッー"
|
||||
- "ファッ!?"
|
||||
- "24時間タタカエマスカ"
|
||||
Loading…
Add table
Reference in a new issue