Bỏ qua để đến nội dung

Tạo dự án từ một repo GitHub

Trỏ một agent vào một repository GitHub và bạn nhận lại một bảng làm việc dùng được ngay: mỗi issue thành một story, ở đúng trạng thái mà lịch sử của nó quy định, kèm theo checklist, nhãn và mốc được mang sang. Rồi cũng chính agent đó nhặt một story lên, nhận nó về mình, đẩy nó qua máy trạng thái và liên kết pull request mà nó đã mở.

Trang này mô tả trọn vòng lặp ấy. Bước tạo dữ liệu có hai lối: GitHub-to-EAT, trình nhập mã nguồn mở của East Agile, làm xong bằng một lệnh (bước 3); API nhập làm đúng công việc đó theo từng lời gọi (bước 4 và 5), và đó là thứ một agent điều khiển khi nó muốn có handle của job. Mọi thứ sau đó đều chạy trên API, bởi trọng tâm là agent có thể tự làm nốt phần còn lại mà không cần ai trông.

Đây không phải một «bản nhập bằng AI» riêng biệt. Bước tạo dữ liệu chính là trình nhập GitHub mà bạn có thể chạy bằng tay từ Cài đặt dự án → Nhập / Xuất, được mô tả trong Hướng dẫn vận hành → Nhập từ các tracker khác. Agent gọi đúng endpoint mà bạn sẽ gọi. Cái trang này bổ sung là tất cả những gì bao quanh nó: ai giữ khóa, kiểm tra bản nhập thế nào trước khi nó ghi, và agent làm gì với bảng khi bảng đã có.

Nguồn GitHub trong tab Import / Export: đã điền owner và repository, để trống token, đánh dấu pull request và milestone

  • Một dự án — và một phiên đăng nhập hoặc một khóa ea_user_… để tạo nó.
  • Một khóa agent — khóa ea_agent_… giới hạn trong dự án đó. Nó cần vai trò nào là tùy bạn muốn agent chạy bao nhiêu phần của vòng lặp; xem bước 2. Xem thêm Hướng dẫn API → Hai loại khóa.
  • Một token truy cập cá nhân GitHub — có quyền đọc issue của repository. Mọi lần nhập đều xác thực, vì việc lấy dữ liệu chạy trên API GraphQL của GitHub và GraphQL từ chối một yêu cầu không mang token. Bạn chỉ được bỏ nó khi Tracker lấy dữ liệu thay bạn: một repository công khai, trên một bản triển khai có token dùng chung dự phòng (dịch vụ eastagiletracker.com được lưu trữ sẵn có một; bản tự lưu trữ không có cái nào cho tới khi người vận hành đặt GITHUB_IMPORT_PAT), và không phải với --engine direct của GitHub-to-EAT. Xem Token và giới hạn tần suất.
  • Node.js 22+ — chỉ cho lối GitHub-to-EAT ở bước 3. Lối qua API không cần gì ngoài curl.

Dự án phải tồn tại trước khóa agent, và phải do một người tạo: khóa agent bị buộc vào một dự án ngay khi được cấp và không thể tự khởi tạo dự án. Hãy tạo nó trong giao diện, hoặc bằng khóa ea_user_… của chính bạn:

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects \
-H "X-TrackerToken: $TRACKER_USER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "hello-world", "iteration_length_weeks": 1}'

Phản hồi mang theo project_id mà mọi lời gọi bên dưới đều cần.

Chủ dự án tạo khóa agent tại Cài đặt dự án → Agent. Vai trò bạn chọn quyết định agent tự làm được bao nhiêu phần của trang này, và có hai câu trả lời hợp lý:

  • owner — một khóa chạy trọn vòng lặp, kể cả nhập dữ liệu. Nhập chỉ dành cho chủ sở hữu, vì một lần nhập viết lại toàn bộ hình hài của dự án. Cấp một agent vai trò owner đòi hỏi chính bạn là chủ dự án: vai trò của agent không bao giờ vượt quá vai trò người tạo ra nó.
  • member — đặc quyền tối thiểu. Agent nhận story, di chuyển chúng, bình luận và liên kết pull request, nhưng không nhập được. Bản nhập bạn tự chạy (bước 5) bằng khóa của mình, rồi trao bảng lại cho agent.

Dù chọn cách nào, đừng để nguyên giá trị mặc định. Một khóa agent mới là viewer chừng nào bạn chưa nói khác đi, và một viewer đọc được bảng nhưng không nhận hay di chuyển được story — tức là gần như toàn bộ vòng lặp này.

Khóa agent quan trọng ở đây vì một lý do vượt ra ngoài quyền truy cập. Một khóa agent hành xử như một người tham gia có tên trong đúng một dự án, nên mọi story nó tạo, mọi thay đổi trạng thái nó thực hiện và mọi bình luận nó viết đều được quy cho agent đó trong lịch sử — phân biệt được với công việc của chính bạn thay vì hòa lẫn vào.

Terminal window
export TRACKER_TOKEN="ea_agent_xxxxx"

Hãy để agent đọc /meta trước mọi thứ khác:

Terminal window
curl https://eastagiletracker.com/api/v1/meta \
-H "X-TrackerToken: $TRACKER_TOKEN"

Nó trả lời hai câu hỏi mà agent lẽ ra phải đoán: khóa bị buộc vào dự án nào (auth.project_id), và mỗi loại story được phép chuyển trạng thái ra sao (transitions). Một feature đi unstarted → started → finished → delivered → accepted; một chore chỉ có unstarted → started → accepted. Đọc tấm bản đồ hơn hẳn viết cứng nó vào mã.

GitHub-to-EAT là trình nhập mã nguồn mở của chính East Agile: một công cụ dòng lệnh giấy phép MIT làm trọn bước tạo dữ liệu — bước 4 và 5 bên dưới — bằng một lệnh. Hãy dùng nó khi có người ngồi trước terminal. Hãy dùng API bên dưới nó khi một agent điều khiển mà không ai trông và muốn có handle của job để hỏi trạng thái.

Nó cần Node.js 22+ và không có phụ thuộc lúc chạy nào của riêng nó. Nó chưa được phát hành lên npm, nên hãy cài từ repository:

Terminal window
git clone git@github.com:EastAgile/GitHub-to-EAT.git
cd GitHub-to-EAT
npm install --global .

Rồi trỏ nó vào khóa bạn cấp ở bước 2 và dự án bạn tạo ở bước 1:

Terminal window
export EAT_AGENT_KEY="ea_agent_xxxxx"
github-to-eat --project $PROJECT_ID --repo octocat/hello-world

Trước tiên nó in một bảng chú giải ánh xạ — chính xác từng loại được chọn sẽ đáp xuống ra sao — và hỏi bạn xác nhận trước khi ghi bất cứ thứ gì. Ngoài terminal, trong một pipe, trong CI hay trong một agent, không có chỗ nào để hiện lời nhắc đó, nên một lần chạy có ghi buộc phải truyền --yes; thiếu nó, công cụ thoát với mã 2 và không ghi gì, thay vì đoán câu trả lời của bạn. Chạy lại là an toàn: thứ đã nhập rồi sẽ bị bỏ qua, không bao giờ nhân đôi.

CờNó làm gì
--dry-runKiểm tra trước, rồi in ra kế hoạch nó sẽ thực hiện — sẽ nhập bao nhiêu story, sẽ bỏ qua bao nhiêu vì đã có — và không ghi gì. Không cần --yes.
--includeNhập những loại nào, phân tách bằng dấu phẩy: issues,prs,milestones,releases,deps. Mặc định là issues, và mọi lựa chọn đều phải chứa nó. Đây cũng chính là các tùy chọn trong bảng ở bước 6.
--tokenToken truy cập cá nhân GitHub của bạn (GITHUB_TOKEN trong môi trường hoặc trong .env cũng được tính). Nó cần quyền repo, hoặc quyền chi tiết Issues: Read, trên repository đó. Bắt buộc với repository riêng tư, với máy chủ không có token dùng chung dự phòng, và luôn luôn với --engine direct. Bỏ nó trên engine mặc định của dịch vụ được lưu trữ thì Tracker tiêu ngân sách dùng chung của chính nó — xem Token và giới hạn tần suất.
--engineserver, giá trị mặc định, gửi một lời gọi /import/json và để Tracker lấy, ánh xạ và ghi. direct chạy đúng pipeline đó trên máy bạn và ghi qua API công khai — tức là nó tự đọc GitHub nên luôn cần token, không có thì thoát với mã 2.
--states, --milestones, --story-type, --no-comments, --no-tasksThu hẹp hoặc ghi đè ánh xạ cho một lần chạy; không có gì được lưu lại. Mỗi cờ trong số đó đều kéo theo --engine direct.

Đặt EAT_API_BASEEAT_APP_BASE để trỏ nó tới một Tracker tự lưu trữ hoặc chạy cục bộ; cả hai mặc định trỏ tới dịch vụ được lưu trữ. README chứa tham chiếu đầy đủ các cờ, các mã thoát và phần khắc phục sự cố.

Mọi thứ bên dưới là chính bản nhập đó nhưng được điều khiển theo từng lời gọi, và đó là thứ bạn muốn khi một agent chạy nó.

Nhập là chỉ dành cho chủ sở hữu — hãy dùng khóa agent vai trò owner, hoặc khóa của chính bạn nếu bạn để agent ở mức member. Hãy chạy nó với dry_run trước, trước khi cho nó ghi bất cứ thứ gì:

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import/json \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"source": "github",
"owner": "octocat",
"repo": "hello-world",
"include_pull_requests": true,
"include_milestones": true,
"dry_run": true
}'

Một lần chạy thử sẽ lấy dữ liệu từ GitHub, đối chiếu và khử trùng lặp y hệt lần thật, báo cáo cùng những con số — imported, skipped, errors, unmatched — rồi hoàn tác toàn bộ giao dịch. Không gì được giữ lại và không sự kiện «đã hoàn tất nhập» nào lọt vào nhật ký kiểm toán của bạn. Đó là cách rẻ nhất để phát hiện rằng bạn vốn định bật mốc, hoặc rằng một repo lớn hơn bạn tưởng, trong khi việc đó còn chưa tốn của bạn đồng nào.

Mọi lời gọi tới /import/json đều bất đồng bộ, kể cả chạy thử: endpoint trả về 202 kèm một handle của job, không phải kết quả, và các con số đến trên job khi bạn hỏi trạng thái nó (bước 5). Job của một lần chạy thử cũng đạt done như lần thật; khác biệt là không gì được ghi.

Bỏ dry_run đi và gửi lại. Như trước, endpoint trả về 202 kèm một handle của job:

{ "import_id": "…", "status": "pending" }

Hỏi trạng thái job cho tới khi nó đạt trạng thái cuối:

Terminal window
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/imports/$IMPORT_ID \
-H "X-TrackerToken: $TRACKER_TOKEN"

Trạng thái đi pending → fetching → writing → done | failed. Chỉ hai trạng thái cuối là trạng thái kết thúc: done mang các con số kết quả, failed mang thông báo lỗi và một mã máy ổn định để bạn rẽ nhánh. Trong lúc việc lấy dữ liệu đang phân trang, progress_currentprogress_total cho biết nó đang ở trang nào — đáng hiển thị nếu có người đang theo dõi.

Token. Truyền "token": "github_pat_…". Bỏ nó đi thì máy chủ thay bằng token nền tảng dùng chung, vốn chỉ đọc repository công khai và được tính vào mọi lời gọi trên bản triển khai — Token và giới hạn tần suất nói rõ điều đó khiến bạn mất gì. Dù dùng token nào, nó chỉ điều khiển các lời gọi lên GitHub và không gì khác: nó không bao giờ vào log, không bao giờ vào nhật ký kiểm toán, không bao giờ được lưu trữ, và không bao giờ được trả lại trong một phản hồi hay một lỗi.

Chạy lại là an toàn. Một hàng đã được nhập trước đó sẽ được khớp theo id nguồn và bị bỏ qua, chứ không nhân đôi. Lần nhập thứ hai bồi thêm vào bảng những gì xuất hiện kể từ lần đầu.

Issue được nhập theo mặc định. Mọi thứ khác đều là tùy chọn, mỗi loại một cờ:

Từ GitHubTrở thànhCờ
IssueMột story. Đang mở → unstarted trong Backlog. Đã đóng → accepted, hoặc rejected khi GitHub cho biết issue được đóng dưới dạng not_planned hay duplicate (story khi đó mang một nhãn tương ứng).mặc định
Checklist trong thân issueTác vụ — mỗi dòng - [ ] / - [x] thành một tác vụ theo thứ tự trong thân, dòng [x] đến nơi đã ở trạng thái hoàn tất. Checklist vẫn ở lại trong phần mô tả.mặc định
NhãnNhãn, mang sang nguyên trạng.mặc định
Pull requestMột story mang nhãn pull-request. Đang mở → started, đã gộp → accepted, đóng mà không gộp → rejected.include_pull_requests
MốcMột epic, đặt tên theo mốc, khử trùng lặp theo tiêu đề — hai issue chung một mốc rơi vào cùng một epic. Khi tắt cờ, nó đi kèm dưới dạng nhãn milestone:<tiêu đề>.include_milestones
ReleaseMột story release. Đã phát hành → accepted, bản nháp → unstarted.include_releases
Phụ thuộc giữa issueMột blocker trên story. Chỉ issue, không bao giờ pull request.include_dependencies

Loại story được suy ra khi issue không nói rõ. Một nhãn chứa bug, fix hay defect — hoặc một tiêu đề bắt đầu bằng fix hay bug — biến nó thành bug; chore, maintenance, devops hay infra biến nó thành chore; còn lại đều là feature. Điều đó đáng biết trước khi nhập, vì trong East Agile Tracker chỉ feature mới mang point và chỉ feature mới góp vào velocity. Xem Giới thiệu → Story.

Bảng dự án ngay sau khi nhập repository mẫu: issue thành story kèm nhãn, milestone thành epic và người dùng GitHub thành owner

Giờ bảng đã có lịch sử, và agent đã có khóa. Từ đây vòng lặp gói gọn trong bốn lời gọi.

Tìm một story, hoặc viết một cái. Lọc bảng để tìm thứ đáng nhặt lên:

Terminal window
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories?state=unstarted" \
-H "X-TrackerToken: $TRACKER_TOKEN"

import_source=github thu hẹp về đúng những gì bản nhập mang vào. Nếu agent tìm ra việc mà repo chưa bao giờ ghi lại, nó tạo story thay vì đi tìm — xem Hướng dẫn API → Tạo một story.

Nhận nó về mình. Agent tự thêm mình làm chủ sở hữu bằng cách POST một thân rỗng:

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/owners \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'

Thân rỗng nghĩa là bên gọi, nên agent không cần biết id của chính mình. Bảng giờ hiển thị agent là chủ sở hữu, và nhờ đó người đang theo dõi biết việc đã có người nhận.

Bắt đầu nó.

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/transitions \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"to": "started"}'

Rồi agent đi làm việc — đọc repo, viết mã, mở pull request. Phần đó diễn ra trong công cụ lập trình của bạn, không phải ở đây.

Đính kèm pull request.

Terminal window
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/links \
-H "X-TrackerToken: $TRACKER_TOKEN" \
-H "Content-Type: application/json" \
-d '{"url": "https://github.com/octocat/hello-world/pull/42"}'

Một URL pull request của GitHub được nhận diện đúng như vậy — bạn không phải nói ra. Story và đoạn mã khép lại nó giờ chỉ cách nhau một cú nhấp, theo cả hai chiều.

Kết thúc nó. Chuyển sang finished rồi dừng ở đó. Một feature vẫn còn deliveredaccepted phía trước, và đó là các cửa soát xét: ai đó không phải agent quyết định rằng công việc đã đúng. Một chore không có cửa ấy — started → accepted là toàn bộ chặng còn lại của nó.

Một issue đã đóng được nhập về, mục CODE liên kết tới pull request đã sửa nó, bên cạnh là các bình luận từ GitHub

Mọi lần nhập đều xác thực. Việc lấy issue, bình luận và pull request chạy trên API GraphQL của GitHub, và GraphQL từ chối một yêu cầu không mang token — không có bậc ẩn danh, dù trên repository công khai hay riêng tư. Câu hỏi không bao giờ là token nào đến GitHub hay không, mà chỉ là token của ai.

Truyền token trong lời gọi nhập, hoặc --token cho GitHub-to-EAT. Một token truy cập cá nhân chi tiết có quyền đọc issue của repository là đủ. Nó chỉ điều khiển các lời gọi lên GitHub và không gì khác: không bao giờ vào log, không bao giờ vào nhật ký kiểm toán, không bao giờ được lưu trữ, và không bao giờ được trả lại trong một phản hồi hay một lỗi.

Hãy mang token của mình cho mọi việc vượt quá một buổi trình diễn. Khi đó bạn tiêu một ngân sách không ai khác chạm vào, và không bước kiểm tra trước nào có thể từ chối bạn vì bản nhập của người khác.

--engine direct không cho bạn lựa chọn. Engine đó đọc GitHub từ máy bạn chứ không qua Tracker, nên token của máy chủ nằm ngoài tầm với; một lần chạy không token sẽ thoát với mã 2 kèm lỗi cách dùng, trước cả khi nó lấy hay ghi bất cứ thứ gì. GITHUB_TOKEN trong môi trường hoặc trong .env của bạn cũng được tính, y như --token.

Thứ bắt buộc phải có token là lượt duyệt issue, không phải cả engine. direct đọc issue, bình luận và pull request qua GraphQL, vốn không có chế độ ẩn danh; nó chỉ chạm tới REST cho danh sách releases và phép dò /rate_limit miễn phí. Công cụ vẫn còn kèm một bộ lấy dữ liệu REST ẩn danh cũ hơn, từng chạy được một lần nhập repository công khai trong hạn mức 60 mỗi giờ, nhưng không đường nào trong CLI còn chạm tới nó và nó sắp bị xóa — vậy hãy coi --token là bắt buộc với direct.

Đừng gửi token nào và máy chủ sẽ thay bằng token nền tảng mà người vận hành đã cấu hình (GITHUB_IMPORT_PAT). Ba giới hạn đi kèm theo nó:

  • Đó là cấu hình tùy chọn. Dịch vụ eastagiletracker.com được lưu trữ sẵn cấp phát một cái, nên lần nhập repository công khai không token vẫn chạy ở đó. Bản tự lưu trữ — tệp nhị phân bạn tải về — không có cái nào cho tới khi người vận hành đặt GITHUB_IMPORT_PAT trong môi trường, và cho tới lúc đó nó từ chối mọi lần nhập không token bằng 400 import_github_no_token.
  • Nó chỉ đọc repository công khai. Dịch vụ được lưu trữ cấp nó ở chế độ chỉ đọc trên các repo công khai, nên một repository riêng tư luôn cần token của chính bạn.
  • Mọi bên gọi trên bản triển khai dùng chung một ngân sách. Trước khi một lần nhập không token chạy, máy chủ đọc số điểm GraphQL còn lại của token dùng chung và từ chối bằng 400 import_github_shared_quota_low khi dưới 500. Ngân sách cạn giữa chừng sẽ khiến job thất bại với import_github_rate_limited_platform. Cả hai thông báo đều chỉ ra cùng một cách khắc phục: cung cấp token của chính bạn.

GitHub đo hai API của mình riêng rẽ, và trần khi không xác thực thấp hơn hai bậc độ lớn.

API GitHubDùng choCó tokenKhông có token
GraphQLIssue, bình luận, pull request, issue con, phụ thuộc5.000 điểm mỗi giờ, tính theo số nút mà truy vấn trả vềBị từ chối — GraphQL không có bậc ẩn danh
RESTRelease (include_releases) và bước kiểm tra trước /rate_limit5.000 yêu cầu mỗi giờ60 yêu cầu mỗi giờ, đếm theo địa chỉ IP và chia chung với mọi người phía sau nó

Một bản nhập không bao giờ rơi xuống bậc 60 lượt mỗi giờ ấy: không có token để gửi thì yêu cầu bị từ chối ngay từ đầu, chứ không thử lại ẩn danh. Con số đó quan trọng với những gì bạn làm xung quanh bản nhập — một script đọc GitHub trực tiếp, hay một shell nằm cùng mạng với các client khác, tiêu hết 60 yêu cầu trong vài giây.

Bạn có thể đọc ngân sách còn lại bất cứ lúc nào; GET /rate_limit được miễn khỏi cả hai giới hạn, nên lần kiểm tra ấy không tốn gì:

Terminal window
curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/rate_limit

Điểm GraphQL không phải là số yêu cầu. GitHub tính điểm một truy vấn theo số nút nó trả về, nên một trang gồm 100 issue kèm bình luận và người được giao đã tốn nhiều điểm, và một repository lớn tiêu hết ngân sách theo giờ trong số lời gọi ít hơn nhiều so với những con số thời REST gợi ra. --dry-run (bước 3) và dry_run (bước 4) mỗi cái tốn đúng số điểm như lần lấy dữ liệu thật — chính điều đó khiến các con số của chúng đáng tin — nên hãy dự trù hai lượt khi bạn kiểm tra trước một bản nhập lớn.

  • Hướng dẫn API — ngữ pháp tìm kiếm, luồng sự kiện, chuyển trạng thái hàng loạt, ghi idempotent và phần còn lại của bề mặt.
  • Hướng dẫn vận hành — cũng những thao tác đó nhưng từ giao diện, và mười trình nhập còn lại.
  • Giới thiệu — vì sao máy trạng thái và bốn loại story lại có hình hài như vậy.
  • GitHub-to-EAT — repository của chính trình nhập: mọi cờ, cả hai engine, và cách đóng góp cho nó.