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
46 changes: 45 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ on:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
- "v[0-9]+.[0-9]+.[0-9]+-beta-[0-9]+"
workflow_dispatch:
inputs:
tag_name:
description: "Release tag name (e.g. v1.2.3 or v1.2.3-beta-1)"
required: true
type: string

jobs:
release-draft:
Expand All @@ -28,6 +34,30 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0

- name: Determine and validate tag
id: resolve-tag
env:
INPUT_TAG_NAME: ${{ inputs.tag_name }}
EVENT_NAME: ${{ github.event_name }}
run: |
if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
TAG="$INPUT_TAG_NAME"
if ! echo "$TAG" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+(-beta-[0-9]+)?$'; then
echo "Error: Tag '$TAG' does not match expected format (e.g. v1.2.3 or v1.2.3-beta-1)"
exit 1
fi
if git ls-remote --exit-code --tags origin "refs/tags/$TAG" >/dev/null 2>&1; then
echo "Error: Tag '$TAG' already exists"
exit 1
fi
else
TAG="${GITHUB_REF_NAME}"
fi
echo "tag_name=$TAG" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"

- name: Setup Go
uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
Expand All @@ -37,7 +67,9 @@ jobs:
cache-dependency-path: "go.sum"

- name: Update VERSION file
run: echo "${GITHUB_REF_NAME#v}" > VERSION
env:
RESOLVED_VERSION: ${{ steps.resolve-tag.outputs.version }}
run: echo "$RESOLVED_VERSION" > VERSION

- name: Cache frontend build
id: cache-frontend-build
Expand Down Expand Up @@ -108,8 +140,20 @@ jobs:
- name: Build Binaries
run: make build-go-binaries

- name: Push release tag
if: github.event_name == 'workflow_dispatch'
env:
RESOLVED_TAG: ${{ steps.resolve-tag.outputs.tag_name }}
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git tag "$RESOLVED_TAG"
git push origin "$RESOLVED_TAG"

- name: Create Release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ steps.resolve-tag.outputs.tag_name }}
draft: true
generate_release_notes: true
files: bin/*
47 changes: 23 additions & 24 deletions docs/en/task-system/03-advanced-and-form-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,48 +31,47 @@ func Register(registry coreinspection.InspectionTaskRegistry) error {

On the "New Inspection" screen in KHI, the system dynamically determines which tasks to include and run in the graph based on the selected environment and log types. To control this behavior, you can attach special labels to inspection tasks.

### 2.1 Filtering with General Label Selectors (`LabelSelector`)
### 2.1 Filtering Tasks with `InspectionTypeLabelSelector`

In current KHI versions, you can attach arbitrary key-value metadata labels to tasks and filter them flexibly using **`LabelSelector`**, which evaluates boolean logic expressions (AND, OR, NOT, etc.) to enable tasks only in specific environments or modes.
In KHI, each `InspectionType` defines a set of key-value labels indicating its target environment, log source, and platform:

- `inspectioncore_contract.InspectionTypeLabelKeyEnvironment` (`"khi.google.com/environment"`)
- `inspectioncore_contract.InspectionTypeLabelKeyLogSource` (`"khi.google.com/log_source"`)
- `inspectioncore_contract.InspectionTypeLabelKeyBasePlatform` (`"khi.google.com/base_platform"`)

To restrict a task so that it only runs for compatible inspection types, attach an `InspectionTypeLabelSelector` label option specifying the required label key-value pairs:

```go
// Set task labels using the general LabelValue option
var AdvancedTask = task.NewTask(AdvancedTaskID, []taskid.UntypedTaskReference{}, func(ctx context.Context) (any, error) {
var AdvancedTask = coretask.NewTask(AdvancedTaskID, []taskid.UntypedTaskReference{}, func(ctx context.Context) (any, error) {
return nil, nil
},
coretask.LabelValue("environment", "gcp"),
coretask.LabelValue("feature-stage", "beta"),
inspectioncore_contract.InspectionTypeLabelSelector(map[string]string{
inspectioncore_contract.InspectionTypeLabelKeyEnvironment: "googlecloud",
inspectioncore_contract.InspectionTypeLabelKeyBasePlatform: "kubernetes",
}),
)
```

During server initialization or inspection configuration, KHI evaluates expressions like the following to select tasks:

```go
selector, _ := labelselector.Parse("environment=gcp && !feature-stage=deprecated")
compatibleTasks := taskSet.Select(selector)
```
When an inspection starts, the runner checks that all key-value pairs in the selector match the selected `InspectionType.Labels`. Tasks without an `InspectionTypeLabelSelector` are treated as global tasks and are included for all inspection types.

### 2.2 Legacy Inspection Type Labels (`InspectionTypeLabel`)

For backward compatibility, you can still use traditional `InspectionTypeLabel` declarations.
This enables the task only for the Inspection Types listed in the label (e.g., GCP Cloud Logging, local log files, etc.).
You can also apply an `InspectionTypeLabelSelector` to all tasks registered in a package by wrapping the registry with `coreinspection.NewScopedRegistry`:

```go
var MyTask = task.NewTask(MyTaskID, []taskid.UntypedTaskReference{}, func(ctx context.Context) (any, error) {
return nil, nil
}, inspectioncore_contract.InspectionTypeLabel(
"example.khi.google.com/inspection-type-1",
"example.khi.google.com/inspection-type-2",
))
func Register(registry coreinspection.InspectionTaskRegistry) error {
scoped := coreinspection.NewScopedRegistry(registry, inspectioncore_contract.InspectionTypeLabelSelector(map[string]string{
inspectioncore_contract.InspectionTypeLabelKeyEnvironment: "googlecloud",
}))
return coretask.RegisterTasks(scoped, TaskA, TaskB)
}
```

### 2.3 FeatureTask Labels
### 2.2 FeatureTask Labels

The FeatureTask label is a special label that exposes a task as a toggleable feature on KHI's "New Inspection" screen.
By specifying this label on main feature tasks such as mappers, you allow users to enable or disable the feature.

```go
inspectioncore_contract.FeatureTaskLabel("my-feature", "Feature label", "Detailed description of the feature", true, "gcp-gke")
inspectioncore_contract.FeatureTaskLabel("Feature label", "Detailed description of the feature", 1000, true)
```

## 3. Task Utilities for Discovering Information from Logs (`Inventory` and `Discovery` Tasks)
Expand Down
47 changes: 23 additions & 24 deletions docs/ja/task-system/03-advanced-and-form-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,48 +31,47 @@ func Register(registry coreinspection.InspectionTaskRegistry) error {

KHI の「New Inspection」画面では、選択された環境やログ種別に応じて、どのタスクをグラフに含めて実行するかが動的に決定されます。これらを制御するために、インスペクションタスクには特別なラベルを付与できます。

### 2.1 汎用ラベルセレクタによるフィルタリング (`LabelSelector`)
### 2.1 `InspectionTypeLabelSelector` によるタスクの絞り込み

現在の KHI では、タスクに対して任意のキー・バリュー形式のメタデータラベルを付与し、それらをブール論理 (AND / OR / NOT 等) の式で表現した **`LabelSelector`** によって、特定の環境やモードでのみ有効化する柔軟なタスク絞り込みを行います。
KHI では、各 `InspectionType` が対象環境やログソース、プラットフォームを表すキー・バリュー形式のラベルを保持しています。代表的なキーは以下の通りです。

- `inspectioncore_contract.InspectionTypeLabelKeyEnvironment` (`"khi.google.com/environment"`)
- `inspectioncore_contract.InspectionTypeLabelKeyLogSource` (`"khi.google.com/log_source"`)
- `inspectioncore_contract.InspectionTypeLabelKeyBasePlatform` (`"khi.google.com/base_platform"`)

特定のインスペクションタイプでのみタスクを実行可能にするには、タスク定義時に `InspectionTypeLabelSelector` ラベルオプションを指定して必要なキー・バリューのペアを設定します。

```go
// 汎用の LabelValue オプションを利用したタスクラベル設定
var AdvancedTask = task.NewTask(AdvancedTaskID, []taskid.UntypedTaskReference{}, func(ctx context.Context) (any, error) {
var AdvancedTask = coretask.NewTask(AdvancedTaskID, []taskid.UntypedTaskReference{}, func(ctx context.Context) (any, error) {
return nil, nil
},
coretask.LabelValue("environment", "gcp"),
coretask.LabelValue("feature-stage", "beta"),
inspectioncore_contract.InspectionTypeLabelSelector(map[string]string{
inspectioncore_contract.InspectionTypeLabelKeyEnvironment: "googlecloud",
inspectioncore_contract.InspectionTypeLabelKeyBasePlatform: "kubernetes",
}),
)
```

これに対して、サーバー初期化時やインスペクション構成時に以下のような式を評価してタスクを抽出します:

```go
selector, _ := labelselector.Parse("environment=gcp && !feature-stage=deprecated")
compatibleTasks := taskSet.Select(selector)
```
インスペクション開始時、ランナーはセレクタに含まれるすべてのキー・バリューが選択された `InspectionType.Labels` に一致するかを検証します。`InspectionTypeLabelSelector` が指定されていないタスクはグローバルタスクとして扱われ、すべてのインスペクションタイプで利用可能になります。

### 2.2 レガシー Inspection Type ラベル (`InspectionTypeLabel`)

互換性のため、従来の `InspectionTypeLabel` も引き続き利用可能です。
このラベルにリストされている Inspection Type (例: GCP Cloud Logging, ローカルログファイル等) でのみタスクを有効化します。
また、パッケージ内で登録する全タスクに一括してセレクタを適用する場合は、`coreinspection.NewScopedRegistry` でレジストリをラップして登録できます。

```go
var MyTask = task.NewTask(MyTaskID, []taskid.UntypedTaskReference{}, func(ctx context.Context) (any, error) {
return nil, nil
}, inspectioncore_contract.InspectionTypeLabel(
"example.khi.google.com/inspection-type-1",
"example.khi.google.com/inspection-type-2",
))
func Register(registry coreinspection.InspectionTaskRegistry) error {
scoped := coreinspection.NewScopedRegistry(registry, inspectioncore_contract.InspectionTypeLabelSelector(map[string]string{
inspectioncore_contract.InspectionTypeLabelKeyEnvironment: "googlecloud",
}))
return coretask.RegisterTasks(scoped, TaskA, TaskB)
}
```

### 2.3 FeatureTask ラベル
### 2.2 FeatureTask ラベル

FeatureTask ラベルは、そのタスクを KHI の「New Inspection」画面におけるトグル可能な機能として公開するための特別なラベルです。
マッパータスクなどの主機能となるタスクに指定することで、ユーザーは機能の有効/無効を選択できます。

```go
inspectioncore_contract.FeatureTaskLabel("my-feature", "機能ラベル", "機能詳細の説明文", true, "gcp-gke")
inspectioncore_contract.FeatureTaskLabel("機能ラベル", "機能詳細の説明文", 1000, true)
```

## 3. ログから情報を発見するためのタスクユーティリティ (`Inventory` と `Discovery` タスク)
Expand Down
19 changes: 5 additions & 14 deletions pkg/core/inspection/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ func (i *InspectionTaskRunner) SetInspectionType(inspectionType string) error {

filteredTasks := []coretask.UntypedTask{}
for _, task := range i.inspectionServer.RootTaskSet.GetAll() {
if i.isTaskCompatible(task, currentType) {
if isTaskCompatible(task, currentType) {
filteredTasks = append(filteredTasks, task)
}
}
Expand All @@ -205,24 +205,15 @@ func (i *InspectionTaskRunner) SetInspectionType(inspectionType string) error {
return i.SetFeatureList(defaultFeatureIds)
}

func (i *InspectionTaskRunner) isTaskCompatible(task coretask.UntypedTask, currentType *InspectionType) bool {
func isTaskCompatible(task coretask.UntypedTask, inspectionType *InspectionType) bool {
labels := task.Labels()

// 1. Evaluate with new Label Selector if present
// 1. Evaluate with Label Selector if present.
if selector, ok := typedmap.Get(labels, inspectioncore_contract.LabelKeyInspectionTypeLabelSelector); ok {
return selector.Match(currentType.Labels)
return selector.Match(inspectionType.Labels)
}

// 2. Fallback to legacy list
if legacyList, ok := typedmap.Get(labels, inspectioncore_contract.LabelKeyInspectionTypes); ok {
if slices.Contains(legacyList, currentType.Id) {
slog.Warn("Legacy inspection type list is used for task. Please migrate to label-selector approach.", "taskID", task.UntypedID().String())
return true
}
return false
}

// 3. Defaults to true if neither is defined (global tasks)
// 2. Defaults to true if no selector is defined (global tasks).
return true
}

Expand Down
Loading
Loading