Skip to content

Commit 437fe89

Browse files
committed
permission
1 parent c53fe62 commit 437fe89

File tree

2 files changed

+141
-4
lines changed

2 files changed

+141
-4
lines changed

.github/workflows/claude.yml

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,70 @@ on:
1111
types: [submitted]
1212

1313
jobs:
14-
claude-code-action:
14+
check-permissions:
1515
if: |
1616
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
1717
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
1818
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
1919
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
2020
runs-on: ubuntu-latest
21+
outputs:
22+
has-permission: ${{ steps.check.outputs.has-permission }}
23+
steps:
24+
- name: Check user permissions
25+
id: check
26+
uses: actions/github-script@v7
27+
with:
28+
script: |
29+
try {
30+
// Get the user who triggered the event
31+
let user;
32+
if (context.eventName === 'issue_comment') {
33+
user = context.payload.comment.user.login;
34+
} else if (context.eventName === 'pull_request_review_comment') {
35+
user = context.payload.comment.user.login;
36+
} else if (context.eventName === 'pull_request_review') {
37+
user = context.payload.review.user.login;
38+
} else if (context.eventName === 'issues') {
39+
user = context.payload.issue.user.login;
40+
}
41+
42+
console.log(`Checking permissions for user: ${user}`);
43+
44+
// Check if user has write access to the repository
45+
const { data: permission } = await github.rest.repos.getCollaboratorPermissionLevel({
46+
owner: context.repo.owner,
47+
repo: context.repo.repo,
48+
username: user
49+
});
50+
51+
const hasPermission = ['admin', 'write', 'maintain'].includes(permission.permission);
52+
console.log(`User ${user} has permission level: ${permission.permission}`);
53+
console.log(`Has required permission: ${hasPermission}`);
54+
55+
core.setOutput('has-permission', hasPermission);
56+
57+
if (!hasPermission) {
58+
core.notice(`User ${user} does not have sufficient permissions to trigger Claude actions. Required: write, maintain, or admin access.`);
59+
}
60+
61+
return hasPermission;
62+
} catch (error) {
63+
console.log(`Error checking permissions: ${error.message}`);
64+
core.setOutput('has-permission', false);
65+
return false;
66+
}
67+
68+
claude-code-action:
69+
needs: check-permissions
70+
if: needs.check-permissions.outputs.has-permission == 'true'
71+
runs-on: ubuntu-latest
2172
permissions:
22-
contents: read
23-
pull-requests: read
24-
issues: read
73+
contents: write
74+
pull-requests: write
75+
issues: write
2576
id-token: write
77+
actions: read
2678
steps:
2779
- name: Checkout repository
2880
uses: actions/checkout@v4

etl/BX_UPDATE.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# ETLの柔軟性向上
2+
3+
## 現状の整理
4+
5+
### ETLで取れるもの
6+
7+
- Community Noteそのもののデータをそのまま一時保存(SQLiteをつかっているが、Postgresqlにいれる方針)
8+
- Community Noteに紐づくPostのデータをX APIをつかって保存(Postgresqlに保存)
9+
- Community Noteのデータを素材に、LLMで言語の推論
10+
- Community Noteのデータを素材に、LLMでトピックの推論
11+
- BirdXplorer API が必要とするデータモデルに変換する
12+
13+
### ETLの手順
14+
15+
現在実装されているETLの手順は以下の通りです:
16+
17+
#### 1. Community Notesデータの取得
18+
- Twitter公式のBirdwatch公開データから日次でCommunity Notesデータを取得
19+
- データソース: `https://ton.twimg.com/birdwatch-public-data/{日付}/notes/notes-00000.tsv`
20+
- 設定可能な日数分遡ってデータを取得([`COMMUNITY_NOTE_DAYS_AGO`](etl/src/birdxplorer_etl/settings.py:18)で制御)
21+
- 重複チェックを行い、新しいノートのみをSQLiteに保存
22+
- 同時にNote Status Historyデータも取得・保存
23+
24+
#### 2. 関連Postデータの取得
25+
- Community Noteに紐づくTwitter投稿をX APIで取得
26+
- 対象期間は設定で制御([`TARGET_TWITTER_POST_START_UNIX_MILLISECOND`](etl/src/birdxplorer_etl/settings.py:12-15)
27+
- 投稿データ、ユーザーデータ、メディアデータ、埋め込みURLデータをPostgreSQLに保存
28+
- 重複チェックにより既存データの再取得を回避
29+
30+
#### 3. データ変換とCSV生成
31+
- **Note変換**: SQLiteからNoteデータを取得し、AIサービスで言語検出を実行してCSV出力
32+
- **Post変換**: PostgreSQLからPostデータを取得してCSV形式に変換
33+
- **User変換**: PostgreSQLからUserデータを取得してCSV形式に変換
34+
- **Media変換**: メディアデータとPost-Media関連付けデータをCSV出力
35+
- **Link変換**: 埋め込みURLデータとPost-Link関連付けデータをCSV出力
36+
37+
#### 4. AIによる高度な変換
38+
- **言語検出**: [`ai_service.detect_language()`](etl/src/birdxplorer_etl/transform.py:75)でNoteの言語を推論
39+
- **トピック推論**: [`ai_service.detect_topic()`](etl/src/birdxplorer_etl/transform.py:310)でNoteのトピックを分類
40+
- トピックマスターデータは[`topic_seed.csv`](etl/seed/topic_seed.csv)から生成
41+
42+
**出力CSVファイル:**
43+
- `note.csv` - ノートデータ(言語情報付き)
44+
- `post.csv` - 投稿データ
45+
- `user.csv` - ユーザーデータ
46+
- `media.csv` - メディアデータ
47+
- `post_media_association.csv` - 投稿-メディア関連付け
48+
- `post_link.csv` - リンクデータ
49+
- `post_link_association.csv` - 投稿-リンク関連付け
50+
- `topic.csv` - トピックマスターデータ
51+
- `note_topic_association.csv` - ノート-トピック関連付け
52+
53+
#### 4. Load(読み込み)フェーズ ([`load.py`](etl/src/birdxplorer_etl/load.py:9))
54+
55+
**S3への出力:**
56+
- 変換されたCSVファイルをAWS S3バケットにアップロード
57+
- タイムスタンプ付きのプレフィックスで整理
58+
- アップロード対象は全9種類のCSVファイル
59+
60+
## 新しくいれるべきもの
61+
62+
### Post取得の効率化
63+
64+
XのPostデータを取得することはコストがかかるので必要なものを優先的に取得するなどが望まれる。例えば、CommunityNoteのデータをもとにAIや条件で先に前処理をしてメタデータをつけて、特定のCommunityNoteのみを対象にしてPostデータを取るなど。
65+
66+
#### 可能性のあるパターン
67+
68+
- CommunityNoteのデータから言語を先に推定し、日本語のみを対象にしてPostデータを取得
69+
- CommunityNoteのデータからキーワードでフィルタし、該当するものを対象にしてPostデータを取得
70+
- 派生パターンとしてはCommunityNoteの条件(HELPFULのみや、日時期間の指定など)によってフィルタし、該当するものを対象にする
71+
- CommunityNoteのデータから特定のトピックに関連するかをAIで推論し、該当するものを対象にしてPostデータを取得
72+
- 以上のパターンを組み合わせてできるようにすることも重要
73+
74+
### Community Noteが紐づいている以外の条件でもPostを取得する
75+
76+
CommunityNoteがついているかかかわらず、特定の条件を満たすPostデータを取得できるようにする。
77+
- ProプランのサーチAPIでの条件検索
78+
- 外部からのデータインポート(協力チームからの提供データをインポートすることを想定。データモデルはBirdXplorerに準拠させるためにコンバーターは別途必要)
79+
80+
### 元データの充実
81+
82+
現状BirdXplorer APIのためにETLがあるという位置づけで機能開発されているものを、それ以外の需要にも対応するために、取れるデータはアーカイブとしてすべて取る。
83+
84+
- 取れるものはすべて取る方針
85+
- X APIのフルアーカイブをつくる(関連するもののみ)

0 commit comments

Comments
 (0)