GitHub Actions น่าจะทำให้ดีขึ้นได้อีกมาก
(blog.yossarian.net)- GitHub Actions มีประโยชน์ทั้งด้านประสิทธิภาพการทำงานและฟีเจอร์ แต่ในการเขียน workflow จริง ความล่าช้าในการดีบัก, ความผิดพลาดด้านความปลอดภัย, การไม่มี type และการขาดแคลน action ทางการ ล้วนทำให้เสียเวลาซ้ำแล้วซ้ำอีก
- แม้จะแก้เล็กน้อยก็ต้องทำ
git add; git commit; git pushและตรวจ log ในเบราว์เซอร์ซ้ำไปมา มีกรณีที่แม้แต่ workflow สำหรับ release แบบง่ายๆ ก็ต้องใช้ commit 4 ครั้งและ release ที่ล้มเหลว 4 ครั้ง - จุดอย่างการขยาย
${{... }},pull_request_target, สิทธิ์เริ่มต้นที่กว้างของGITHUB_TOKENและการอ้างอิง SHA ของ fork ล้วนเป็นจุดด้านความปลอดภัยที่พลาดได้ง่าย โดยเฉพาะ fork SHA ที่อาจดูเหมือน commit ของ repository ที่ตั้งใจใช้งาน - input ของ action ไม่มีการตรวจสอบ
type:และขอบเขตการรองรับก็แตกต่างจากworkflow_call·workflow_dispatchทำให้แทนที่จะใช้อินพุตแบบ array หรือ object ได้ ต้องจัดการเองด้วย สตริงแบบ CSV หรือ input ที่ถูกทำให้แบน - การตรวจสอบตอน push, runtime security check, การลดสิทธิ์ token เริ่มต้นของ repository ส่วนตัว, type checking ที่เข้มงวดขึ้น และ action ทางการ·กึ่งทางการที่มากขึ้น จะช่วยเพิ่มความน่าเชื่อถือของ workflow ได้
GitHub Actions มีประโยชน์ แต่ก็คอยสะดุดซ้ำๆ
- GitHub Actions เป็นเครื่องมือที่ช่วยเพิ่มประสิทธิภาพการทำงานและความมั่นคงในการทำงานอย่างมาก จนถูกใช้ทุกวันทั้งในโปรเจกต์มืออาชีพและโปรเจกต์งานอดิเรกมาตั้งแต่ปี 2019
- การขยายฟีเจอร์ก็มีมาอย่างต่อเนื่อง
- ถึงอย่างนั้น ในกระบวนการพัฒนาจริงก็ยังกลายเป็นสาเหตุของ ความหงุดหงิดและการเสียเวลาอย่างมาก ได้
การดีบักหนักเกินไป แม้เป็นข้อผิดพลาดเล็กๆ
- มีกรณีที่ระหว่างตั้งค่า workflow สำหรับ release ต้องใช้ commit 4 ครั้ง และ release ที่ล้มเหลว 4 ครั้ง เพื่อจับข้อผิดพลาดเล็กๆ
- ไม่ได้ใช้
${{ ... }}ในจุดที่จำเป็น - ลืมความสัมพันธ์
needs:
- ไม่ได้ใช้
- วงจรการดีบักปัจจุบันมีหลายขั้นตอนเกินไป แม้เพียงตรวจสอบความผิดพลาดง่ายๆ หนึ่งอย่าง
- ต้องสลับจากสภาพแวดล้อมพัฒนาไปยังเบราว์เซอร์
- ต้องหาแท็บที่ถูกต้อง
- ต้องคลิกเข้าไปในหน้า summary และ status ของ Actions
- ต้อง refresh log console ที่ถูก buffer ไว้เพื่อหาข้อผิดพลาดถัดไป
- แม้เป็นการเปลี่ยนแปลงเล็กๆ ทั้งกระบวนการก็อาจใช้เวลา มากกว่า 30 วินาที
-
แนวทางปรับปรุง
- ควรมี interactive debugging shell หรืออย่างน้อยควรสามารถ rerun workflow จากการเปลี่ยนแปลงเล็กๆ ได้โดยไม่ต้อง
git add; git commit; git push - ควรมีการตั้งค่า repository ให้ปฏิเสธ workflow ที่ผิดชัดเจนได้ตั้งแต่ตอน push
- syntax ที่ไม่มีทางทำงานได้
- การอ้างอิง job หรือ step ที่ไม่มีอยู่จริง
- กรณีที่ workflow ไม่ทำงานเงียบๆ เพราะ YAML ผิด
- ควรมี interactive debugging shell หรืออย่างน้อยควรสามารถ rerun workflow จากการเปลี่ยนแปลงเล็กๆ ได้โดยไม่ต้อง
ความผิดพลาดด้านความปลอดภัยเกิดขึ้นง่ายเกินไป
- ใน GitHub Actions workflow ที่ผู้ใช้เขียนอาจเปราะบางโดยไม่ตั้งใจได้ง่าย
- เมื่อใช้การขยาย
${{ ... }}ใน shell หรือบริบทการรันอื่น หากค่าที่ขยายมาจาก input ที่ผู้ใช้ควบคุมได้ อาจนำไปสู่การ inject โค้ดอันตราย- ในตัวอย่าง มีการ inject โค้ดผ่าน
inputs.frobและอาจทำให้$MY_IMPORTANT_SECRETรั่วไหล
- ในตัวอย่าง มีการ inject โค้ดผ่าน
pull_request_targetใช้อย่างปลอดภัยได้ยากมากใน workflow ที่ไม่ใช่เรื่องเล็กน้อย- use case ที่ตั้งใจไว้ดูเหมือนเป็นขอบเขตแคบๆ เช่น การติด label หรือเขียน comment ให้ PR ที่มาจาก fork
- แต่ในทางปฏิบัติกลับถูกเปิดให้เป็น foot-gun ขนาดใหญ่
- สิทธิ์ระดับ workflow และ job ก็ถูกตั้งไว้กว้างเกินไปได้ง่าย
- สิทธิ์เข้าถึงเริ่มต้นของ
GITHUB_TOKENปกติกว้างมาก - ใน repository ของบัญชีส่วนตัว มักลืมลดสิทธิ์ token เริ่มต้น
- เพราะไม่รู้แน่ชัดว่าต้องใช้สิทธิ์ขอบเขตไหน จึงมักให้สิทธิ์ token มากเกินไป
- สิทธิ์เข้าถึงเริ่มต้นของ
- โมเดลสิทธิ์ของ GitHub ยัดทุกอย่างลงในแกนเดียวคือ
read/write/noneจึงยิ่งทำให้สับสนid-token: writeทำให้อ่าน OpenID Connect token ของ workflow ได้- การทำงาน
GETบางอย่างของ security advisory ต้องใช้สิทธิ์writeส่วนบางอย่างใช้แค่read
Action ที่ปัก SHA อาจสับสนกับ commit ของ fork ได้
- reference ที่ดูเหมือน
actions/checkout@c7d749a2d57b4b375d1ebcd17cfbfb60c676f18eอาจไม่ใช่ commit ของ repositoryactions/checkoutจริงๆ - SHA ดังกล่าวเป็น commit ที่อยู่ใน fork ภายใน network ของ
actions/checkoutและเพราะ GitHub ใช้ alternates จึงอาจดูเหมือนอยู่ใน repository หลัก - บทความที่เกี่ยวข้องของ Chainguard แบ่งปัญหาออกเป็นสามข้อ
- การอ้างอิง SHA ของ fork กับ SHA ของ repository เป้าหมายแยกแยะด้วยตาไม่ออก
- GitHub REST API
/repos/{user}/{repo}/commits/{ref}จะคืน JSON response ที่อ้างอิงแค่{user}/{repo}แม้{ref}จะมีอยู่เฉพาะใน fork - หากแยก SHA ของ fork กับ non-fork ไม่ได้ อาจเลี่ยงข้อจำกัดด้านแหล่งที่เชื่อถือของ GitHub Actions ได้
- การตอบสนองของ GitHub จนถึงตอนนี้อยู่ในระดับเพิ่ม ข้อความเพิ่มเติม ลงในเอกสารเท่านั้น
-
แนวทางปรับปรุง
- ต้องมีโหมด paranoid workflow security ที่ปฏิเสธ workflow ที่เห็นชัดว่าไม่ปลอดภัยตั้งแต่ตอน push
- เช่นเดียวกับ runtime instrumentation แบบ AddressSanitizer ควรทำให้ pattern ที่เสี่ยงด้านความปลอดภัยล้มเหลวระหว่างรัน workflow ได้
- ตัวอย่าง: ใน
pull_request_targetหากใช้actions/checkoutกับ ref ที่ไม่ใช่ repository เป้าหมาย ให้ fail
- ตัวอย่าง: ใน
- อาจพิจารณาเลิกใช้หรือถอด
pull_request_targetออก - แม้ใน repository ส่วนตัว ก็ควรตั้งขอบเขต
GITHUB_TOKENเริ่มต้นให้จำกัดมากขึ้นได้เหมือน organization·enterprise - action ที่ pin ด้วย SHA ซึ่ง SHA นั้นไม่มีใน repository ที่อ้างถึงและมีอยู่เฉพาะใน fork ควรถูกปฏิเสธโดยค่าเริ่มต้น
Type system ขาดความสม่ำเสมอและพลังในการแสดงข้อมูล
- GitHub Action แบบ custom สามารถกำหนด input ใต้
inputs:ได้ แต่ input ของ action ไม่มี การบังคับ type - declaration อย่าง
type: numberใช้ไม่ได้กับ input ของ action - ภายใน GitHub Actions เอง ตำแหน่งที่รองรับ type ก็ไม่สม่ำเสมอ
workflow_call: รองรับboolean,number,stringworkflow_dispatch: รองรับboolean,choice,number,string- action inputs: ไม่รองรับ type
- แม้ input ที่รองรับ type ก็ไม่รองรับโครงสร้างข้อมูลซับซ้อนอย่าง array หรือ object
- ใช้ input แบบ array เช่น
paths: [foo, bar, baz]ไม่ได้ - ใช้ input แบบ object ที่มีโครงสร้างลำดับชั้นใต้
headers:ไม่ได้
- ใช้ input แบบ array เช่น
- ผู้เขียน action จึงต้องขอ input ในรูปแบบเฉพาะกิจแทน
- ต้อง implement การ parse แบบ CSV เอง เช่น
paths: foo,bar,baz - ทำให้โครงสร้างลำดับชั้นที่เป็นธรรมชาติแบนลง เช่น
header-foo,header-baz
- ต้อง implement การ parse แบบ CSV เอง เช่น
- วิธีแบบนี้ไม่ดีทั้งต่อการบำรุงรักษาและความปลอดภัย
- ต้องจัดการ namespace ของ input แบบแบนเดียวเอง
- ต้องสร้างภาษาที่ไม่ได้ระบุสเปกอย่างเป็นทางการขึ้นมาเพื่อ input ที่ซับซ้อน
-
แนวทางปรับปรุง
- ผู้เขียน action และ workflow ควรใช้
type:ได้ทุกที่ choiceก็ไม่ควรถูกจำกัดไว้เฉพาะworkflow_dispatchแต่ควรใช้ได้ทุกที่- ในกรณีที่อนุมาน type แบบ static ได้ ควรปฏิเสธการเปลี่ยนแปลง workflow ที่ใช้ type ผิดตั้งแต่ตอน push
- ต้องมี
type: objectและtype: array - แม้อาจไม่สมบูรณ์แบบเพราะ type ภายในอาจหลากหลาย แต่ก็ยังดีกว่าปัจจุบัน
- หากจำเป็น ก็ส่งผ่านเป็นสตริงที่ serialize เป็น JSON ได้
- GitHub Actions มีฟังก์ชัน
fromJSON(...)อยู่แล้ว
- ผู้เขียน action และ workflow ควรใช้
Action ทางการเชื่อมโยงโดยตรงกับความเชื่อมั่นต่อแพลตฟอร์ม
- ecosystem ของ third-party ใน GitHub Actions มี action คุณภาพสูงจำนวนมาก
- ใต้ ecosystem นั้นมี action ทางการที่ GitHub ดูแลอยู่
- งาน
gitหลัก:actions/checkout - งาน GitHub และการจัดการ repository:
actions/{upload,download}-artifact,actions/cache,actions/stale - การตั้งค่าที่จำเป็น:
actions/setup-python,actions/setup-node
- งาน
- Action เหล่านี้มีความทั่วไปและความสำคัญสูง จึงมีคุณค่ามากหากมี implementation ที่ดูแลอย่างเป็นทางการ
- แต่จำนวน action ทางการมีน้อย และบางงานที่เชื่อมต่อฟีเจอร์ของ GitHub โดยตรงก็ไม่ได้ถูก提供เป็น action ทางการ
- ตัวอย่าง: action ที่เพิ่ม pull request เข้า merge queue แบบ programmatic
- GitHub CLI มี
gh pr mergeแต่ไม่ได้ expose เป็น action
-
ตัวอย่าง action ทางการที่หยุดดูแล
actions/create-release: หยุดดูแลตั้งแต่มีนาคม 2021- ผู้ใช้ถูกแนะนำให้ย้ายไปใช้ workflow ที่ดูแลโดย community
- ตัวอย่างที่ถูกกล่าวถึงคือ
softprops/action-gh-release actions/upload-release-asset: ถูกระบุว่าหยุดดูแลในช่วงเดียวกับactions/create-releaseactions/setup-ruby: หยุดดูแลตั้งแต่กุมภาพันธ์ 2021- ผู้ใช้ถูกแนะนำให้ย้ายไป
ruby/setup-ruby - การย้ายเองค่อนข้างเจ็บปวดน้อย แต่ภาพว่าคอมโพเนนต์หลักอาจถูกทิ้งได้ส่งผลเสียต่อความเชื่อมั่นในแพลตฟอร์ม
- หาก action ทางการคุณภาพสูงมีไม่พอ ผู้ใช้จะต้องจัดการพื้นผิวของ GitHub API เอง และยังคงสร้างความผิดพลาดด้านความปลอดภัยต่อไป
-
แนวทางปรับปรุง ecosystem
- งานที่เชื่อมส่วนต่างๆ ของ infrastructure GitHub เข้าด้วยกันโดยตรง และปัจจุบันต้องทำเองผ่าน REST API call หรือรัน
ghควรถูกนำเสนอเป็น action ทางการ - อาจร่วมมือกับ third-party action ขนาดใหญ่เพื่อสร้าง องค์กรกึ่งทางการ อย่าง
community-actions- action ที่ผ่านการ review จาก GitHub
- ปฏิบัติตาม best practices ด้านความปลอดภัยของ repository
- อัปเดตตาม semantic version
- เส้นทางความเชื่อมั่นที่ชัดเจนสำหรับ action สำคัญใน ecosystem
- งานที่เชื่อมส่วนต่างๆ ของ infrastructure GitHub เข้าด้วยกันโดยตรง และปัจจุบันต้องทำเองผ่าน REST API call หรือรัน
เครื่องมือที่มีอยู่และ roadmap ของ GitHub
- หลายคนแนะนำ
nektos/actซึ่งเป็นเครื่องมือจำลอง GitHub Actions แบบ local- มีประโยชน์ในการ iterate และดีบัก workflow ง่ายๆ อย่างรวดเร็ว
- แต่บางกรณี image และ event ไม่เหมือนกับสภาพแวดล้อมจริงของ GitHub อย่างสมบูรณ์ จึงถูกมองว่าเป็นเครื่องมือที่มี loss
rhysd/actionlintใช้สำหรับ local linting และ security linting- ข้อจำกัดคือ lint ได้เฉพาะ workflows แต่ lint actions ไม่ได้
- GitHub Actions extension for VS Code ให้การ lint ใน editor และการผสาน repository workflow
- อ้างอิงจาก public JSON schema
- แสดง workflow ที่กำลังรัน, เติมตัวแปรให้อัตโนมัติ และอื่นๆ
- แต่ยังมีปัญหาที่ตรวจไม่พบ เช่น พิมพ์ชื่อ secrets ผิด หรือพิมพ์ชื่อ output ที่สร้างแบบ dynamic ผิด ทำให้การดีบักแบบ add-commit-push ยังจำเป็นอยู่
- Julian Dunn ผู้รับผิดชอบการจัดการโปรเจกต์ GitHub Actions แชร์ฟีเจอร์และลำดับความสำคัญบางส่วนที่กำลังดำเนินอยู่
- interactive debugging อยู่ใน public roadmap ของ GitHub Actions
- งานย้ายจาก workflow pinning แบบ tag·SHA ไปสู่วิธีที่เป็น immutable มากขึ้น ก็อยู่ใน public roadmap
- GitHub มองว่าสุขภาพและคุณภาพของ ecosystem action ทางการเป็นลำดับความสำคัญ และใช้กลยุทธ์คงจำนวน action ทางการไว้ไม่มาก เพื่อให้สามารถดูแลและให้ความสนใจกับแต่ละ action ได้เพียงพอ
1 ความคิดเห็น
ความคิดเห็นจาก Hacker News
เวิร์กโฟลว์ของ GitHub Actions มีอยู่สองแนวทาง 1) “เขียนโปรแกรม” ด้วย GitHub Actions โดยเรื่องอย่างการส่งอีเมลก็เอาเครื่องมือจาก marketplace มาต่อเพิ่ม ทำให้ YAML โตเป็น 500–1000 บรรทัด เต็มไปด้วยเงื่อนไขจนเข้าใจยาก
2) ใช้ GitHub Actions แค่เป็น “การตั้งค่า” แล้วถามตัวเองอยู่เสมอว่า “ผลักความซับซ้อนของ YAML นี้ไปไว้ในสคริปต์ได้ไหม?” ถ้าใส่การส่งอีเมลไว้ในสคริปต์ เวิร์กโฟลว์ก็จบที่ราว 50–60 บรรทัด และสามารถดีบักสคริปต์ในเครื่องได้ ทำให้วงจร push-debug-commit แบบโง่ ๆ แทบหายไป ทุกครั้งที่ไปทีมใหม่ ผมจะบอกว่าแบบที่ 1 คือเส้นทางสู่ความบ้าคลั่ง ส่วนแบบที่ 2 คือแนวทางที่สมเหตุสมผล แต่ราวครึ่งหนึ่งก็ยังเลือกแบบที่ 1 อยู่ดี ถ้าเลือกแบบที่ 2 ปัญหาเรื่อง เครื่องมือดีบักไม่เพียงพอ และ vendor lock-in ก็จะเป็นปัญหาน้อยลงมาก
แต่หลายครั้ง การผลักทุกอย่างเข้าไปไว้ในภาษาโปรแกรมที่เหมาะสมก็ยังไม่พอ อาจต้องใช้ฟีเจอร์เฉพาะ vendor ของ GHA, แสดง dependency ระหว่างงาน หรือเรียก REST API ที่ถูก abstract ไว้อย่างดีแล้วในรูปของ action อยู่แล้ว แม้จะนำไปเขียนใหม่ด้วยภาษาที่ต้องการได้ แต่ vendor dependency ก็ไม่ได้หายไป และยังเปราะบางอยู่ดี สุดท้าย value proposition เรื่อง vendor lock-in ของ GHA นั้นแข็งแรงมาก ดังนั้นหากจะโน้มน้าวคนให้เลือกข้อ 2 จำเป็นต้องมีข้อดีที่แรงกว่านี้
เรื่องนี้ไม่ได้ใช้ได้เฉพาะกับ GHA แต่กับ build server ทุกตัว Build server ควรเป็น ตัวรันสคริปต์ ที่เพิ่มประวัติ การจัดการ artifact และสิทธิ์/การ audit เข้าไป ส่วนกระบวนการ build จริงควรมอบหมายให้ repository ที่เป็นเป้าหมายของการ build
อนึ่ง มี nektos/act ที่พยายามจำลองการทำงานของ GHA ในเครื่อง: https://github.com/nektos/act
ควรเขียน build/test/sign/deploy ฯลฯ เป็นสคริปต์ให้ portable มากที่สุดเท่าที่ทำได้ และสคริปต์เหล่านี้ต้องทำงานบนเครื่อง local ได้เสมอ มอง GitHub เป็นเพียงตัวที่เตรียมสภาพแวดล้อมสำหรับรันสคริปต์นั้นโดยอัตโนมัติและสั่งรันจริงเท่านั้น
ลูป git commit, push, wait เป็นประสบการณ์ผู้ใช้ที่แย่มาก ผู้ใช้ควรได้ใช้ pipeline ที่ portable ซึ่งรันได้ทุกที่ รวมถึงบนเครื่อง local ด้วย Act ช่วยแก้ปัญหานี้ได้ระดับหนึ่ง แต่โดยทั่วไปก็ไม่ได้แทนสภาพแวดล้อมจริงได้ตรงทั้งหมด
มี pipeline จำนวนมากที่รันในเครื่องเหมือน production ไม่ได้ แต่ในขั้นตอนพัฒนาที่สำคัญน้อยกว่า ก็ไม่มีเหตุผลที่จะไม่ capture เวิร์กโฟลว์เหล่านี้แล้วรันในเครื่อง Garden ให้ pipeline แบบ portable และเพิ่ม caching ครอบคลุม dependency graph ทั้งหมด ลูกค้าบางรายลดเวลารันได้มากกว่า 80% และนักพัฒนาเห็นผลว่า test ผ่าน/ไม่ผ่านได้ทันทีโดยไม่ต้อง push เข้า git ก่อน เป็นโอเพนซอร์ส: https://github.com/nektos/act, https://docs.garden.io
make releaseเห็นด้วยอย่างยิ่งกับความเจ็บปวดในการดีบักการรัน GH Actions เครื่องมือที่มีก็มีแค่เปิดดีบักแล้วรันใหม่เท่านั้น มี คอมมิตขยะ ที่ทำขึ้นมาเพื่อแก้หรือดีบัก pipeline เยอะเกินไป และส่วนใหญ่ก็เป็นแค่การลองโยนอะไรมั่ว ๆ เข้าไปเพื่อดูว่าจะเวิร์กไหม
แม้แต่งานพื้นฐานมาก ๆ อย่าง logic ที่นำกลับมาใช้ซ้ำได้ ก็ยังซับซ้อนโดยไม่จำเป็นหรือมีเอกสารแย่ พอรู้แล้วมันก็ค่อนข้างง่าย แต่เอกสารของ GitHub แย่มาก ดูเหมือนว่าถ้าต้องการ reuse จะต้องทำ action ให้เป็นสาธารณะหรือเอาไปไว้ใน repository อื่น แต่จริง ๆ แล้วสามารถสร้างไฟล์ YAML ใหม่ที่มี logic สำหรับใช้ซ้ำได้ เพียงแต่ต้องวางไว้ที่ root ของโฟลเดอร์ workflows ถึงจะทำงาน GH Actions ใช้งานแล้วทรมานจริง ๆ แต่พอมันทำงานได้แล้วก็สะดวกมาก อยากให้มีอะไรอย่าง local runner สำหรับทดสอบ action ก่อน commit และ push
ไม่ใช่ปัญหาของ GitHub เท่านั้น แพลตฟอร์ม CI รายใหญ่อื่น ๆ ก็ไม่ได้ดีกว่ากันเท่าไรในแง่ workflow และ integration ตอนนี้พยายามทำทุกอย่างให้เป็นสคริปต์ให้มากที่สุด
GitHub Actions เป็นระบบ CI/CD ที่แย่มาก ไม่สามารถรันขั้นตอนแบบขนานบน VM เดียวกันได้ และงานที่อิง container ก็ถูกปฏิบัติเหมือนพลเมืองชั้นสอง
ปัญหาแรกทำให้ไม่สามารถ parallelize การตั้งค่า credentials ในเครื่องหรือ dependency ของ environment ได้ เห็น
google-github-actions/setup-gcloudใช้เวลาเกิน 1 นาทีแล้วหงุดหงิด ปัญหาที่สองทำให้การใช้ Dockerfile ใน repository เพื่อระบุการตั้งค่า environment ของ CI เป็นเรื่องยากมาก รวมถึงให้ CI rebuild image เมื่อเนื้อหา image เปลี่ยน แล้วให้ workflow ที่พึ่งพา image นั้นรอ และถ้าเนื้อหาไม่เปลี่ยนก็ไม่ต้อง rebuild แต่รันได้ทันทีพร้อม dependency ที่ติดตั้งไว้แล้ว ใน GitHub Actions สุดท้ายมักต้องพยายามเติม cache ใหม่ทุกครั้ง cache จำกัดที่ 5GB เพิ่มไม่ได้แม้จะจ่ายเงิน และถูกไล่ออกแบบ FIFO ดังนั้นถ้าเกิน 5GB ก็แทบเหมือนไม่มี cache คิดถึง Concourse มาก มันทำ parallel jobs, custom pipeline triggers, SSH เข้าไปใน CI environment เพื่อดีบัก, รันงานครั้งเดียวโดยไม่ต้องมี pipeline, ส่งต่อเนื้อหา directory ระหว่างงานโดยไม่ต้องสร้าง artifact ได้ GitHub Actions ใกล้เคียงกับ CI/CD ของเล่น ที่ดังเพราะเริ่มใช้ง่าย แค่วางไฟล์หนึ่งไว้ใน.github/workflowsก็ใช้ได้ เหมาะกับการดึงคนเข้ามาใช้ แต่เมื่อเกินฟีเจอร์ช่วงแรกไปแล้ว มันยังไม่ทรงพลังพอจะเรียกว่า “ดีที่สุด”การดีบักผ่าน SSH กับงานแบบครั้งเดียวมันเหมือนฝันจริง ๆ
ไม่เข้าใจว่าทำไมยังไม่แก้เรื่องที่ GitHub แยกการอ้างอิง SHA จาก fork กับ non-fork ไม่ได้ จน fork สามารถหลบการตั้งค่าความปลอดภัยของ GitHub Actions ได้
ถ้าการควบคุมความปลอดภัยถูกหลบได้ง่าย ๆ นั่นคือ ประเด็นความปลอดภัยร้ายแรง จริงอยู่ที่ต้องโน้มน้าวให้ใครบางคนใช้ SHA ของเรา แต่ social engineering โดยทั่วไปก็เป็นทางที่ง่ายอยู่แล้ว
พูดตรง ๆ คือมันแย่จนรู้สึกอายเลยด้วยซ้ำ แปลกด้วยที่ build ล้มเหลวแบบไม่เกี่ยวข้องจะส่งแจ้งเตือนไปหา maintainer ล่าสุดที่ merge เป็นคนสุดท้ายโดยบังเอิญเท่านั้น ถ้า maintainer คนใหม่ไม่บอกทาง Matrix ผมอาจไม่รู้เลยว่า update/build ของผมล้มเหลวมาหนึ่งสัปดาห์แล้ว
cache action เห็นด้วยตาเปล่าก็ชัดว่าพัง แต่ดูเหมือนไม่มีคนดูแล ถ้า UI พังหรือแท็บถูก unload ก็ tail build log ของขั้นตอนไม่ได้ แทบไม่มี abstraction สำหรับทำให้ workflow portable ระหว่าง worker node image พื้นฐานก็เกือบเป็นหายนะ ตอนแรกแค่รำคาญว่ามันบวมเกินไป แต่ยิ่งขุดลงไปก็ยิ่งรู้สึกว่า “คนของ Microsoft ที่ไม่รู้จัก Linux เป็นคนรับผิดชอบแน่ ๆ” ไม่มีความพยายามจะให้ image ที่เบากว่าสำหรับคนที่ใช้ Nix หรือ Docker เลย กำลังย้ายออกจาก GitHub อยู่ และเหตุผลหลักคือ Actions ทำให้ตาสว่างขึ้นมา เหตุผลที่ไม่อยากเขียนโปรแกรมด้วย YAML คือมองว่า YAML เป็นความอัปยศที่เกิดจากเงิน VC ไหลเข้า ecosystem ที่ไม่รู้จักเทคโนโลยีสมัยใหม่และมีประโยชน์จริง
ขอแนะนำ https://pre-commit.ci อย่างยิ่ง ผมไม่ได้เกี่ยวข้องกับบริการนี้ แค่เป็นผู้ใช้ที่พอใจเท่านั้น
แนวคิดคือเขียน hook หรือใช้ hook ที่มีอยู่แล้วเพื่อตรวจโค้ดก่อน commit และแก้ไขถ้าทำได้ จากนั้นหลัง push แล้ว CI จะตรวจอีกครั้ง และถ้าจำเป็นก็จะทำ commit แก้ไขให้อัตโนมัติด้วย ระบบแคชอัตโนมัติดีมากจนเร็วอย่างไม่น่าเชื่อ และเพราะใช้ การตั้งค่าเดียวกัน ทั้งบนเครื่องพัฒนาใน local และบน CI จึงลดปัญหาในการดีบักไปได้มาก ใช้กับโอเพนซอร์สได้ฟรี มันไม่ได้ทำอย่าง release อัตโนมัติ แค่ตรวจสอบเท่านั้น แต่ก็ทำการตรวจสอบนั้นได้ดีมาก
ถ้าต้องการตรวจซอร์สโค้ดเอง ก็สามารถรัน static check ได้ด้วย
skip_install = Trueแค่รันในคอนเทนเนอร์ที่ติดตั้ง tox เป็นเครื่องมือ global และมี Python เวอร์ชันที่จำเป็นทั้งหมดอยู่แล้ว ตัวอย่างเช่นมี image อย่าง https://github.com/georgek/docker-python-multiversion แม้จะไม่ได้ดูแลต่อแล้ว แต่ก็อัปเดตได้ง่าย boilerplate ประมาณใส่[tox] envlist = py{310,311},[testenv], และใน[testenv:check]ใส่pre-commit run --all-files --show-diff-on-failureก็เพียงพอแล้วหลังจากเจอลูป
git commit; git push; repeatมากเกินไป ผมก็พบ https://github.com/mxschmitt/action-tmate มันเปิด shell access ให้ระหว่างขั้นตอนต่าง ๆ จึงไม่ได้แก้ปัญหาทุกอย่าง แต่บางครั้งก็ช่วยลดความเจ็บปวดได้อย่างชัดเจนโดยส่วนตัว อยากให้แนบ รายงาน HTML เข้ากับ action run ได้โดยไม่ต้องใช้ของอย่าง
actions/upload-artifactในตอนนี้โดยเฉพาะใน test build มักมีหลายครั้งที่อยากดูรายงาน HTML ที่ output ออกมาอย่างรวดเร็ว วิธีที่รู้ตอนนี้คือ upload-artifact หรือ GH Pages แต่ GH Pages ไม่ค่อยเหมาะเมื่อมี output รายงานหลายชุดใน repository เดียวกัน หรือเมื่ออยากดูรายงานเก่าอย่างรวดเร็วแทนที่จะเป็นรายงานล่าสุด คงจะดีถ้ามี action ง่าย ๆ อย่าง
attach-reportที่แนบลิงก์รายงาน HTML ไว้ในสรุปงาน แล้วพอคลิกก็ render HTML ให้ ระบบ CI/CD อัตโนมัติอื่น ๆ รองรับการจับและดูรายงาน HTML เป็นพื้นฐานได้ครบถ้วนกว่านี้มาก$GITHUB_STEP_SUMMARYได้โดยตรง โดยไม่ต้องผ่านการอัปโหลด artifact หรือขั้นตอนทำนองนั้นผมมองว่า GH Actions แทบจะเป็นการ rebrand “Azure Pipelines” ของ Microsoft เสียมากกว่า จากมุมมองของคนที่เคยใช้ build และ release pipelines ของ TFS/VSTS/AzDO มาทุกรูปแบบก่อนหน้านี้ ทีมนี้ทำสิ่งนี้ได้ไม่ค่อยดี
ที่ Azure Pipelines พอจะใช้งานได้ ก็เพราะวิธีทั้งหมดที่พยายามมาก่อนหน้านั้นล้มเหลวจริง ๆ เคยมีโปรเจกต์สำหรับรัน pipeline ใน local เพื่อให้ทำลูป edit-run-debug ในสภาพแวดล้อมส่วนตัวได้โดยไม่ต้อง commit แต่แน่นอนว่าถูกยกเลิกไป: https://github.com/microsoft/azure-pipelines-agent/pull/2687/files#diff-570b52bcb927a5365c22d17a21e8e19e1ba3427c7f3ec16ea64b7b3d14e4ee20 อย่างไรก็ดี ก็ยังมีเครื่องมือที่ช่วยเพิ่มคุณภาพชีวิตอยู่ เช่น VS Code extension ที่เข้าใจ syntax: https://marketplace.visualstudio.com/items?itemName=ms-azure-devops.azure-pipelines ถ้าพูดแบบชวนถกเถียงหน่อย หากใช้ XML แทน YAML แค่ประกาศ xmlns ที่ด้านบน ก็อาจได้การตรวจสอบความถูกต้องจาก code editor ดี ๆ ส่วนใหญ่โดยแทบไม่ต้องให้ผู้ใช้ทำอะไรเพิ่มเติม XML นั้นเลวร้ายก็จริง แต่ก็มีฟีเจอร์มีประโยชน์มากมายที่เราสูญเสียไปพร้อมกับการทิ้งมันทั้งหมด