Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/claude-code-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
fetch-depth: 1

Expand Down
71 changes: 71 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: release

on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
tag:
description: "再リリースする既存タグ (例 v0.1.0)"
required: true

# 既定はトークンを read のみに絞り、リリースジョブだけ write に昇格する。
permissions:
contents: read

# 同一タグへの連続 push / 手動再実行で公開ジョブが多重起動し、Release 作成や
# アセット添付が競合しないよう直列化する (実行中のジョブはキャンセルしない)。
concurrency:
group: release-${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
cancel-in-progress: false

jobs:
release:
name: Build and publish release archives
runs-on: ubuntu-latest
permissions:
# GitHub Release の作成・アセット添付に必要 (最小権限)。
contents: write

steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
# git describe --tags のタグ解決と SOURCE_DATE_EPOCH (git log %ct) の双方に
# 全履歴・タグが必要。浅いチェックアウトだとバージョンがハッシュへフォール
# バックし、アーカイブの mtime も不定になる。
fetch-depth: 0
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/{0}', github.event.inputs.tag) || github.ref }}

- name: Set up Go
uses: actions/setup-go@v6
with:
# バージョンの単一情報源は go.mod。check-latest で go.mod が指すバージョンを
# 確実に取得する (ランナー同梱の Go に依存しない)。新しい Go の取り込みは go.mod の更新で行う。
go-version-file: go.mod
check-latest: true
Comment thread
yuu61 marked this conversation as resolved.

- name: Run tests
# 公開前にタグのコミットでテストを通し、壊れたバイナリの出荷を防ぐ。
run: make test

- name: Build cross-platform archives and checksums
# ビルド・アーカイブ・チェックサムは Makefile が単一の情報源 (CLAUDE.md)。
# 同一コミットに複数タグがある場合に git describe が別タグを拾わないよう、
# 公開する tag を VERSION として明示的に渡し tag_name と一致させる。
run: make package VERSION=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}

- name: Publish GitHub Release
uses: softprops/action-gh-release@v3
with:
tag_name: ${{ github.event_name == 'workflow_dispatch' && github.event.inputs.tag || github.ref_name }}
# 自動生成ノートはタグ push 時のみ。手動再実行で手書きのリリースノートを上書きしない。
generate_release_notes: ${{ github.event_name == 'push' }}
files: |
dist/*.tar.gz
dist/*.zip
dist/SHA256SUMS
# GITHUB_TOKEN は自動注入。上の contents:write で fork (yuu61/deadman) へ公開できる。
# 注意: fork からの pull_request では token が read-only になり Release 作成に失敗するため、
# この workflow に pull_request trigger を足さないこと。
63 changes: 63 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ GOLANGCI ?= golangci-lint
# golangci-lint を `make tools` で入れる際のバージョン (現行 v2 系)。
GOLANGCI_VERSION ?= v2.12.2

# アーカイブ生成に使う外部ツール (macOS で GNU tar を使う場合は `make package TAR=gtar`)。
# zip の変数は ZIP_BIN とする: Info-ZIP の zip は環境変数 $ZIP / $ZIPOPT を既定オプション
# として読むため、make 変数を ZIP と名付けて export すると引数解釈が壊れる (出力が作られない)。
TAR ?= tar
ZIP_BIN ?= zip

BIN_NAME := deadman
PKG := ./cmd/deadman
BIN_DIR := bin
Expand All @@ -18,6 +24,15 @@ EXE := $(shell $(GO) env GOEXE)
# git から導出するバージョン文字列 (タグが無ければコミットハッシュ、未コミット差分は -dirty)。
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo dev)

# アーカイブを決定的にするためコミット日時を SOURCE_DATE_EPOCH に固定する
# (tar の mtime 正規化・gzip -n と併用)。環境変数が設定されていればそちらを優先。
SOURCE_DATE_EPOCH := $(or $(SOURCE_DATE_EPOCH),$(shell git log -1 --pretty=%ct 2>/dev/null || echo 0))

# zip は SOURCE_DATE_EPOCH を解さないため、固める前に touch で各ファイルの mtime を固定する。
# touch -d @epoch は GNU 専用なので、GNU/BSD 双方が解せる touch -t 形式 (ホスト TZ) へ変換する。
# date が epoch を扱えない環境でも決定性を失わないよう、最終手段として DOS 下限の 1980-01-01 に倒す。
SOURCE_DATE_TOUCH := $(or $(shell date -d @$(SOURCE_DATE_EPOCH) +%Y%m%d%H%M.%S 2>/dev/null || date -r $(SOURCE_DATE_EPOCH) +%Y%m%d%H%M.%S 2>/dev/null),198001010000.00)

# リリースビルド用フラグ。-s -w でシンボルを除去、-trimpath で絶対パスを排除して再現性を上げる。
# -X main.version で git 由来のバージョン文字列をバイナリへ埋め込み、TUI のタイトル表示に反映する。
LDFLAGS := -s -w -X main.version=$(VERSION)
Expand Down Expand Up @@ -48,6 +63,54 @@ cross: ## 全プラットフォーム向けにクロスコンパイル (dist/
$(GO) build $(BUILDFLAGS) -o $$out $(PKG) || exit 1; \
done

.PHONY: package
package: ## リリース用アーカイブ(.tar.gz/.zip)と SHA256SUMS を dist/ に生成 (要 GNU tar/gzip/zip/sha256sum)
@command -v $(ZIP_BIN) >/dev/null 2>&1 || { echo "error: zip が見つかりません (Debian/Ubuntu: apt install zip / macOS: brew install zip)" >&2; exit 1; }
@$(TAR) --version 2>/dev/null | grep -q 'GNU tar' || { echo "error: GNU tar が必要です (macOS: brew install gnu-tar してから make package TAR=gtar)" >&2; exit 1; }
@mkdir -p $(DIST_DIR)
@# 旧アーカイブ・make cross の素バイナリ・中断で残ったステージを一掃して、古い版が混ざらないようにする。
@rm -rf $(DIST_DIR)/$(BIN_NAME)-* $(DIST_DIR)/SHA256SUMS
@case "$(VERSION)" in \
*-dirty) echo "warning: VERSION=$(VERSION) — 作業ツリーが汚れています。クリーンなタグ付きの木で実行してください。" >&2 ;; \
dev) echo "warning: VERSION=dev — git 情報がありません。リリースには git tag vX.Y.Z を推奨します。" >&2 ;; \
*-[0-9]*-g[0-9a-f]*) echo "warning: VERSION=$(VERSION) はタグから先行したコミットです。リリースはタグ直上のコミットで実行してください。" >&2 ;; \
v[0-9]*) : ;; \
*) echo "$(VERSION)" | grep -Eq '^[0-9a-f]{7,40}$$' \
&& echo "warning: VERSION=$(VERSION) はコミットハッシュです。リリース前に git tag vX.Y.Z を付けてください。" >&2 || true ;; \
esac
@for p in $(PLATFORMS); do \
os=$${p%/*}; arch=$${p#*/}; \
ext=; [ "$$os" = windows ] && ext=.exe; \
name=$(BIN_NAME)-$(VERSION)-$$os-$$arch; \
stage=$(DIST_DIR)/$$name; \
echo ">> $$stage"; \
rm -rf $$stage; mkdir -p $$stage; \
CGO_ENABLED=0 GOOS=$$os GOARCH=$$arch \
$(GO) build $(BUILDFLAGS) -o $$stage/$(BIN_NAME)$$ext $(PKG) || exit 1; \
cp deadman.conf LICENSE $$stage/ || exit 1; \
sed '/](img\//d' README.md > $$stage/README.md || exit 1; \
chmod 0755 $$stage/$(BIN_NAME)$$ext; \
chmod 0644 $$stage/deadman.conf $$stage/README.md $$stage/LICENSE; \
if [ "$$os" = windows ]; then \
find $$stage -exec touch -t $(SOURCE_DATE_TOUCH) {} + 2>/dev/null || true; \
( cd $(DIST_DIR) && rm -f $$name.zip && ZIP= ZIPOPT= TZ=UTC $(ZIP_BIN) -qrX $$name.zip $$name ) || exit 1; \
else \
$(TAR) --sort=name --mtime="@$(SOURCE_DATE_EPOCH)" \
--owner=0 --group=0 --numeric-owner \
--pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime \
-C $(DIST_DIR) -cf $(DIST_DIR)/$$name.tar $$name || exit 1; \
gzip -nf $(DIST_DIR)/$$name.tar || exit 1; \
fi; \
rm -rf $$stage; \
done
@cd $(DIST_DIR) && \
if command -v sha256sum >/dev/null 2>&1; then HASH="sha256sum"; \
elif command -v shasum >/dev/null 2>&1; then HASH="shasum -a 256"; \
else echo "error: sha256sum/shasum が見つかりません" >&2; exit 1; fi; \
set --; for f in *.tar.gz *.zip; do [ -e "$$f" ] && set -- "$$@" "$$f"; done; \
if [ "$$#" -gt 0 ]; then $$HASH "$$@" > SHA256SUMS && echo ">> $(DIST_DIR)/SHA256SUMS"; \
else echo "warning: アーカイブが無いため SHA256SUMS を生成しません。" >&2; fi

.PHONY: install
install: ## go install で $GOBIN/$GOPATH/bin に導入
$(GO) install $(BUILDFLAGS) $(PKG)
Expand Down
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,32 @@ go run ./cmd/deadman deadman.conf
go install github.com/yuu61/deadman/cmd/deadman@latest
```

## インストール(リリース版バイナリ)

[Releases](https://github.com/yuu61/deadman/releases) から OS / アーキテクチャに合ったアーカイブをダウンロードして展開します。
linux / macOS は `.tar.gz`、Windows は `.zip` で、ファイル名は `deadman-<version>-<os>-<arch>` 形式です(中の実行ファイル名は常に `deadman` / `deadman.exe`)。
展開すると `deadman-<version>-<os>-<arch>/` という単一ディレクトリになり、実行ファイル・設定例 `deadman.conf`・README・LICENSE が入っています。

```sh
tar xzf deadman-v0.1.0-linux-amd64.tar.gz # Windows: deadman-v0.1.0-windows-amd64.zip を展開
cd deadman-v0.1.0-linux-amd64
./deadman deadman.conf # Windows: .\deadman.exe deadman.conf
```

同梱の `deadman.conf` は監視対象の**例**です。実際の監視先に書き換えて使ってください(既存の設定ファイルがある場合は上書きに注意)。設定の文法は「[設定ファイル](#設定ファイル)」を参照してください。

完全性は Releases に併載の `SHA256SUMS`で検証できます。アーカイブと一緒にダウンロードしてください。

```sh
# ダウンロードしたアーカイブと SHA256SUMS を同じディレクトリに置いて実行
sha256sum --ignore-missing -c SHA256SUMS
# macOS: shasum -a 256 -c SHA256SUMS (全アーカイブを置くか、対象 1 件を手動照合)
```

Linux で raw ソケットや権限が必要な場合は「[権限とプラットフォームに関する注意](#権限とプラットフォームに関する注意)」を参照してください。

> **メンテナ向け**: 配布アーカイブは `make package` で `dist/` に生成されます(`.tar.gz` / `.zip` と `SHA256SUMS`、要 `zip` / GNU `tar`)。`git tag -a vX.Y.Z` を付けて `git push origin vX.Y.Z` すると `release` ワークフローが全プラットフォーム分をビルドして GitHub Release へ公開します。

## 使い方

```sh
Expand Down
Loading