คุณต้องการอะไรจาก Forge?
(lobste.rs)- ประเด็นที่นำมาพูดคุยคือเวิร์กโฟลว์แบบ Git ล้วน ๆ ที่ผู้ใช้ Jujutsu และระบบควบคุมเวอร์ชันอื่น ๆ เห็นว่า forge หลัก ๆ ยังรองรับได้ไม่เพียงพอ
- ความสนใจหลักไม่ได้อยู่ที่วิธีการนำไปใช้ เช่น SPA/JS หรือ HTML ที่เรนเดอร์จากฝั่งเซิร์ฟเวอร์ แต่อยู่ที่ว่ารีโพซิทอรี แสดงออกและทำงาน กับความสามารถด้านการควบคุมเวอร์ชันอย่างไร
- มีแนวคิดอย่าง Tangled, stacked PRs ของ GitHub และ forgefed อยู่แล้ว แต่หาพื้นที่ที่รวบรวมความเห็นผู้ใช้เกี่ยวกับการออกแบบได้ยาก
- รวมถึง stacked PR/MR และโมเดลการทำงานร่วมกันแบบทางเลือก โดยประเด็นสำคัญคือประสบการณ์ด้านการควบคุมเวอร์ชันที่ก้าวข้าม forge แบบเดิม
- การแสดง อ็อบเจ็กต์ในรีโพซิทอรี เช่น tag, commit, tree และ blob ส่วนใหญ่คล้ายกันในแต่ละ forge และแทบไม่มีการถกเถียงนอกจากความต่างเล็กน้อยด้านรูปแบบ
1 ความคิดเห็น
ความคิดเห็นจาก Lobste.rs
คอมเมนต์รีวิวโค้ด ถ้าไม่ใช่ส่วนหนึ่งของตัวรีโพซิทอรีเองก็ใช้ไม่ได้เด็ดขาด
การเก็บบริบททางประวัติศาสตร์ที่มีค่าไว้ใน mailing list, database silo หรือชั้นแยกต่างหากที่ไม่ยึดกับแฮชคอมมิต HEAD โดยพื้นฐานแล้วมีความเสี่ยงแบบเดียวกับ GitHub
Fossil ไปในทิศทางนี้อยู่บ้าง แต่ยังจัดการแค่ issue และรีวิวโค้ดยังเป็นแบบ email patch อยู่: https://fossil-scm.org/home/doc/tip/www/contribute.wiki
พอข้อมูลนี้เข้าไปอยู่ในระบบควบคุมเวอร์ชันแล้ว ก็สามารถครอบด้วยเว็บ UI สวย ๆ, RSS feed, mailing list ได้
ฟีเจอร์ที่สองคือการรองรับ merge queue แบบบิวท์อิน สำหรับโปรเจ็กต์ที่ไม่ใช่ระดับเล็ก ๆ ผู้ร่วมพัฒนาแต่ละคนไม่ควร push เข้า main branch โดยตรง และเมื่อมาร์กคอมมิตใดว่า “พร้อมรวมแล้ว” บอตก็ควร serialize การเปลี่ยนแปลงที่เสนอ, จัดตาราง CI ให้เหมาะที่สุด และเลื่อน main ไปยังแฮชที่ผ่านการตรวจสอบแล้ว
ฟีเจอร์ที่สามคือ CI ในฐานะตัวรันงานแบบแยกสภาพแวดล้อมบนระบบที่หลากหลายอย่าง Windows, macOS เป็นต้น: https://gregoryszorc.com/blog/2021/…
ทุกคนควรสมัครบัญชีและเปิด issue ได้ แต่ต้องไม่มีสแปม
ตอนนี้ GitHub ทำเรื่องนี้ได้ค่อนข้างดี บางทีก็ยังเห็นสแปมบ้าง แต่พอรายงาน abuse แล้วก็ถูกลบเร็วมาก น่าจะมีทั้งระบบอัตโนมัติจำนวนมากกับทีมมนุษย์คอยคัดแยกอยู่เบื้องหลัง
กำลังดู Fossil เป็น “forge” สำหรับโปรเจ็กต์งานอดิเรกอยู่ แต่คงไม่มีผู้ร่วมพัฒนาจากภายนอกมากนัก เลยรู้สึกว่ารีวิวโค้ดมีก็ดี ไม่มีก็ได้
แต่อยากได้ SQLite DB ที่ซิงก์ได้ ส่งต่อได้ และ query ได้ตามใจ
สิ่งที่อยากทำเป็นรีแฟกเตอร์ใหญ่ถัดไปใน git-pr คือเปิด SQLite DB ผ่านคำสั่ง SSH:
ssh pr.pico.sh sqlSQLite มีอยู่แทบทุกที่และอเนกประสงค์เท่าที่ต้องการ แต่ยังขาด usability ในการถูกใช้งานเป็นส่วนหนึ่งของ forge
แต่อยากรู้ว่าถ้า ประวัติถูกเขียนใหม่ อย่าง force push หรือ squash merge แล้ว คอมเมนต์เหล่านั้นจะถูก “ปัก” ไว้ตรงไหนภายหลังให้ผู้ใช้หาเจอ
ใน GitHub จุดยึดนั้นคือ Pull Request เลยยังเห็นการสนทนาได้แม้คอมมิตที่รวมอยู่จะเปลี่ยนไป
เลยสงสัยว่าระบบนี้จะมีแนวคิด PR แยกต่างหากที่เก็บในรีโพซิทอรีด้วยหรือเปล่า หรือคาดหวังอะไรที่ผสานแน่นกว่านั้น
แต่ก็ใช้
jjได้ดีอยู่ เลยอาจไม่ใช่ปัญหาใหญ่ในทางปฏิบัติก็ได้พอได้ใช้ทั้ง Gerrit และอีเมล ก็รู้สึกเสียดายที่ โมเดล pull request กลายเป็นกระแสหลักที่สุด
โดยเฉพาะเวลาที่ maintainer ควรจะแก้จุดเล็ก ๆ เรื่องสไตล์เองได้เลย แทนที่จะคอมเมนต์ทิ้งไว้ และฝั่งผู้ร่วมพัฒนาก็มักไม่ได้สนใจเรื่องสไตล์ขนาดนั้น
แต่ที่น่าเสียดายยิ่งกว่าคือทุกวันนี้แทบไม่มี workflow ที่ไม่ใช่อีเมลสำหรับ Darcs หรือ Pijul ซึ่งคนใช้กันมากขึ้นเรื่อย ๆ
อยากได้แบบ XMPP-based แทนอีเมล เพราะจะทำให้ร่วมมือกันแบบกระจายตัวได้แบบเรียลไทม์กับ patch ที่กำลังทำอยู่ และอาจมี MUC หนึ่งห้องต่อหนึ่ง patchset ก็ได้
MUC เปิดใช้ได้เหมือนแชตเสียง และมีฟีเจอร์อย่าง role, ไฟล์แนบ, reaction, การค้นหา, MAM, moderation และ tombstoning หลังเสร็จงาน ซึ่งถูกนิยามไว้ใน XEP แล้ว
ใช้ PubSub สำหรับการ subscribe ได้ และใช้เป็นช่องทางส่ง CI ได้ด้วย
ถ้าจะให้ใช้งานได้จริงคงต้องมีไคลเอนต์เฉพาะ แต่หลายฟีเจอร์ก็น่าจะทำงานได้เลยบนไคลเอนต์ทั่ว ๆ ไป
ในความเป็นจริง อาจใกล้เคียงกับที่ช่วงนี้ผมชอบเห็นเทคโนโลยีแบบ federated เก่า ๆ ขยายตัวอย่างคาดไม่ถึงมากกว่า
การรีวิวโค้ดและการอนุมัติ คือคอขวด
การสื่อสารกับผู้ส่งโค้ดมี latency สูงมาก บางทีกินเวลาเป็นสัปดาห์หรือเป็นเดือน และยังเชื่อถือไม่ได้ด้วย บางคนเปิด PR แล้วก็หายไปเลย
โมเดล GitHub ที่ตั้งอยู่บนสมมติฐานว่าต้องมีการโต้ตอบไปกลับตรงนี้จึงพังหมด
ถ้าระหว่างรีวิวแก้โค้ดได้โดยตรงและ amend คอมมิตได้แบบ
git-absorbก็คงดี การไปกลับกับผู้ส่งเพราะเรื่องเล็กน้อยอย่างพิมพ์ผิดเป็นการเสียเวลา และการแฮ็กด้วย Edit Suggestion ของ GitHub ก็ยุ่งยากและทำให้ประวัติรกผมไม่อยากรีวิวโค้ดเดิมซ้ำ ถ้ามีปัญหาแค่ฟังก์ชันเดียวหรือคอมมิตเดียว ก็ควรอนุมัติส่วนที่เหลือไว้ล่วงหน้าได้ และเมื่อผู้ส่งแก้ด้วย force push แล้วก็ไม่ควรต้องกลับมาดูใหม่ทั้งหมด
ควร merge ได้แค่บางส่วนของ PR หรือเอาคอมมิตออกได้โดยไม่ต้องปิด PR บางครั้งไม่ต้องการฟีเจอร์นั้นเอง แต่ยังอยากเก็บงานพื้นฐานที่ทำมาแล้วไว้ หรือกลับกันก็มี “งานเก็บกวาด” หรือ formatting ที่ไม่จำเป็นปนเข้ามา
เวลาผู้ส่งต้นฉบับไม่ตอบสนอง คนอื่นก็ควรเข้ามาร่วมมือ ขัดเกลา และแก้ปัญหาใน PR นั้นต่อได้ ในโมเดล GitHub ก็พอทำได้ในทางทฤษฎี แต่ในทางปฏิบัติเหมือนเป็นทริกลับ ๆ ที่ต้องทำ PR ใส่ PR อีกที และโค้ดกับการแจ้งเตือนนั้นก็ไม่ปรากฏในโปรเจ็กต์เป้าหมาย ถ้าคนไป fork แล้วส่ง PR แก้กลับมา ก็ยิ่งมีแต่ความสับสนและ merge conflict
บ่อยครั้งโค้ดที่ส่งมาก็ใช้ได้ค่อนข้างดีแล้ว แค่อยากให้ปรับปรุงอีกนิด จากมุมผู้ส่งจะรู้สึกเหมือน PR ถูกจับเป็นตัวประกันจนกว่าจะเก็บรายละเอียดให้หมด ส่วนจากมุม maintainer ถ้า merge ไปก่อนก็เสี่ยงว่าผู้ส่งจะหายไปและงานปรับปรุงต่อจะไม่เกิดขึ้นเลย อยากได้วิธี merge แบบชั่วคราวโดยมีพันธะว่าต้องกลับมาเก็บงานทีหลัง เช่น merge เข้า staging branch ได้ แต่ยังไม่ cherry-pick ไป stable branch จนกว่า FIXME จะถูกแก้
ในโปรเจ็กต์โอเพนซอร์สยอดนิยม มักเกิดสถานการณ์ที่มีคนเพียง 1 คนที่ทำรีวิวและอนุมัติโค้ดเพื่อพาโปรเจ็กต์เดินหน้าได้ แต่มีคนอีก 500 คนที่อยากมีส่วนร่วมและช่วยกัน โมเดล GitHub ใช้ประโยชน์จากกำลังส่วนเกินของผู้ร่วมพัฒนาเหล่านี้ไม่ได้เลย แทนที่จะช่วยให้ร่วมมือกัน กลับแปลงมันเป็นวิกฤต ความสับสน และแรงกดดันจากฝูงชนที่โกรธเกรี้ยว ควรรองรับการจัดการ fork และการคัดลอกโค้ดข้าม fork ให้ดีกว่านี้ เพื่อให้คนอื่นทดลองและพัฒนาโปรเจ็กต์ต่อได้โดยไม่ติดที่ maintainer คนเดียว และเพื่อให้ maintainer เลือกหยิบการเปลี่ยนแปลงที่ได้รับความนิยมและพิสูจน์แล้วว่าใช้ได้จากหลาย fork ได้ง่าย
จำได้ว่าสำหรับ organization นี่น่าจะเป็นค่าเริ่มต้นอยู่แล้ว ไม่ว่าอย่างไร ในกรณีนี้ก็ force push แก้ให้สะอาดได้ตรง ๆ
ผมทำแบบนั้นเสมอสำหรับการแก้เล็ก ๆ ที่ไม่คุ้มจะคุยไปกลับ
ปกติรู้สึกว่าเป็นหน่วยเดือนหรือปีเลย
บางทีก็เป็นผมเองที่เป็น maintainer และผมก็ยอมรับว่าตัวเองไม่ได้เร็วกว่านี้เสมอไป
อยากได้ฟีเจอร์อย่าง go to definition หรือ hover popup ที่แสดง signature กับ doc comment
ถ้า checkout branch มารีวิวใน editor ที่ชอบก็ทำได้ แต่ก็อย่างที่บอกไป คอขวดอยู่ที่การรีวิว
พอต้องรีวิวหลาย PR งานเพิ่มจากการสลับ branch ไปมาก็เยอะเกินไป
ต้องมีโหมด ผู้ใช้คนเดียว หรืออย่างน้อยก็โหมดผู้ใช้คนเดียว
ทำไมต้องยอมรับ URL แบบ https://code.chrismorgan.example/chrismorgan/repository-name ด้วย? ในเมื่อ https://code.chrismorgan.example/repository-name ก็พอ
ผมพูดจริงนะ และถ้าดู https://github.com/go-gitea/gitea/issues/11028 ก็ชัดว่ามีคนอยากได้แบบนี้เยอะ
หนึ่งในสามเหตุผลหลักที่ผมไม่มีบัญชี Fediverse ก็เพราะที่อยู่มันน่าเกลียด
ถ้าใช้อะไรอย่าง @me@chrismorgan.info เป็นอีเมลหลัก บางคนอาจมองเห็นมันเป็นแค่ “@me” แต่ @chrismorgan@chrismorgan.info นี่แค่เห็นก็ไม่ชอบแล้ว
เรื่องนี้ ATProto ทำได้ดีมาก ชื่อโดเมนเป็น handle ที่ยอดเยี่ยม และถ้าต้องมีผู้ใช้หลายคนก็ใช้ subdomain ก็พอ
แม้แต่บน shared forge ถ้าใช้ subdomain ก็น่าจะทำให้รู้สึกเหมือนเป็นผู้ใช้คนเดียวได้ ลองนึกภาพ chris-morgan.github.com แทน github.com/chris-morgan ก็น่าสนใจดี
ความสวยงามสำคัญ
การไปทางผู้ใช้คนเดียวมีผลลัพธ์ที่ใหญ่กว่านั้นด้วย ถึงจะย่อ Mastodon ให้ใช้คนเดียวก็ยังหนักอยู่ดี แต่โปรเจ็กต์ Fediverse ที่ออกแบบมาสำหรับผู้ใช้คนเดียวตั้งแต่ต้นจะเหมาะกับการใช้งานแบบนั้นกว่า
ผมอยากดูแลเซิร์ฟเวอร์เอง โดยมี ผู้ใช้ในเครื่องแค่ผมคนเดียว และไม่อยากประนีประนอมเพียงเพราะอาจมีผู้ใช้อื่น
นี่หมายความด้วยว่า สำหรับ forge ผมอยาก push โดยใช้ชื่อผู้ใช้
chrisแบบ SSH ปกติ ไม่ใช่ชื่อทั่วไปอย่างgitถ้าเป็น forge ตามความหมายที่เข้าใจกันทั่วไป การ federation ก็ควรมีอยู่แล้ว แต่บน “home server” ของแต่ละคน อยากให้มีผู้ใช้โลคัลแค่คนเดียว
ถ้าใช้โดเมนชื่อตัวเอง ตรงนั้นก็มีปัญหาคล้ายกันไม่ใช่หรือ?
ผมชอบ บทความของ Nesbitt ในหัวข้อนี้
โดยเฉพาะเรื่อง การสื่อสารกับ downstream ที่ดีกว่าเดิม
ควรทำ รีวิวโค้ดแบบโลคัล ได้ใน editor ที่เลือกใช้
ผมไม่อยากถูกขังอยู่ในเว็บอินเทอร์เฟซทื่อ ๆ ที่เปลี่ยนฟอนต์ไม่ได้และมี syntax highlighting แย่มาก
ตอนนี้ใช้ workflow ที่มีเครื่องมือ custom สำหรับ Neovim เพื่อดู diff แบบเทียบกันข้าง ๆ ให้ดีขึ้น และใช้คำสั่ง
git prเพื่อ checkout pull requestแต่พออยากได้อะไรเพิ่มอีกนิด เช่น การทิ้งคอมเมนต์รีวิว ก็ต้องไปพึ่ง CLI ของใครสักคนหรือเครื่องมือที่คุยกับ GitHub API ซึ่งมีโอกาสน้อยมากที่จะยังได้รับการดูแลอีก 5 ปีข้างหน้า
ให้พูดให้ชัดคือ ไม่ใช่แค่เครื่องมือที่ “รันได้” แบบโลคัลเท่านั้น แต่ต้องการ เครื่องมือแบบ local-first ที่เชื่อมกับ editor และสิ่งแวดล้อมฝั่งโลคัลได้มากกว่า
เหตุผลที่สิ่งนี้เป็นฟีเจอร์ระดับ first-class ได้ยากคือแรงงานที่ต้องใช้สูง เว็บอินเทอร์เฟซหนึ่งตัว “ทำงาน” ได้บนทุกแพลตฟอร์มและทุกสภาพแวดล้อม editor เพราะมันบังคับผู้ใช้ แต่การเชื่อมที่แน่นกว่านั้น ถ้ามี editor กับ environment อยู่ N แบบ ก็ต้องมี integration N แบบ
CI ก็เหมือนกัน ผมอยากรันเทสต์บน Linux, FreeBSD, macOS ได้ง่าย ๆ โดยไม่ต้อง push คอมมิตไปที่ branch แล้วรอ 15 นาทีให้มันถูกหยิบไปรัน
แค่ประมาณ
run-remotely some-command --on freebsd,linux,macก็น่าจะพอโดยพื้นฐานแล้วมันควรเป็นระบบ CI แบบ local-first และกระจายศูนย์ แต่ในขณะเดียวกันก็ต้องรองรับระบบกลางที่เป็นแหล่งความจริงหนึ่งเดียว เพื่อรับประกันว่าโค้ดทั้งหมดผ่านระบบ “ที่อนุมัติแล้ว” เดียวกันก่อน merge
นี่ไปไกลกว่าแค่
ssh user@host command ...เพราะต้องรวมถึงการคัดลอกซอร์สโค้ด, caching, การติดตั้ง dependency ที่ต้องใช้ ฯลฯ เพื่อให้ได้สภาพที่เชื่อถือได้เหมือนกันทุกครั้งเพียงแต่ผมไม่คิดว่านี่ควรเป็นฟีเจอร์ของ forge มันควรเป็นเครื่องมือ task runner ที่ใช้ได้แม้ไม่มี forge ตัวใดเลย และเรียกใช้จาก forge ไหนก็ได้
ผมคิดว่ามันควร “driver-based” หน่อย ๆ คือจะรันงานเดียวกันแบบโลคัลล้วน ๆ ก็ได้ หรือส่งไปให้ระบบรีโมตรันก็ได้ งานนั้นอาจรันใน VM, ในคอนเทนเนอร์ หรือรันตรง ๆ ก็ได้
ต้องรองรับ ระบบควบคุมเวอร์ชันที่ไม่ใช่ Git ด้วย
ควรนำเข้าและส่งออก issue, wiki ฯลฯ ได้ในฟอร์แมตที่ใช้งานสะดวก เพื่อไม่ให้ติดกับระบบใดระบบหนึ่ง
และควร self-host ได้ง่ายด้วย
น่าจะมีขอบเขตบางส่วนที่สำคัญจริง ๆ อยู่
Heptapod ในคอมเมนต์ข้างเคียงก็เป็นของ Mercurial และ sourcehut, also ก็มี
Fossil มี forge ของตัวเอง และ allura ซึ่งเป็น Apache เวอร์ชันของ SourceForge ก็รองรับ Subversion
อยากให้มี forge ที่ให้สิ่งแบบ แนว Bazel ในชั้น CI
ไม่ใช่แค่ “รัน Bazel ใน CI ได้” แต่เป็นรูปแบบที่ชักนำให้คนเขียนชุดเทสต์และบิลด์ที่ดีพร้อม dependency อย่างเป็นธรรมชาติ เพื่อไม่ให้เผาเวลาของ CI ไปโดยไม่มีเหตุผล
ที่เกี่ยวข้องกันคือผมคิดว่าโมเดล “หนึ่งโปรเจ็กต์ = หนึ่งรีโพซิทอรี” สร้างปัญหาไว้มาก
จะเรียกว่าเป็นการรองรับ monorepo ที่ดีกว่าก็ได้ แต่โดยพื้นฐานแล้วสิ่งอย่าง CI และ issue ควรถูกกำหนดขอบเขตได้ใหญ่กว่าแค่ “ระดับบนสุดของไดเรกทอรีนี้”
หลายโปรเจ็กต์แยกรีโพซิทอรีเพราะเหตุผลของ forge หรือ CI และการทำงานในสภาพนั้นไม่สนุกเลย
ในฐานะ reviewer ผมก็อยากได้ การแยกแพตช์แบบ inline
หมายถึงอยากเลือกส่วนที่คิดว่าดีและอนุมัติเฉพาะส่วนนั้น เพื่อรวมส่วนที่น่าพอใจได้เลย
ผมยังรู้สึกว่า stacked PR เป็นแนวคิดที่หนักเกินไป
ถ้าใครบอกว่า “ผมอยากแก้ 4 ไฟล์และมองว่านี่คือ PR เดียว” reviewer ก็ควรตอบได้ว่า “โอเค 2 ไฟล์นี้ใช้ได้” แล้วทำชุดการเปลี่ยนแปลงนั้นให้เป็นส่วนแยกของ PR หรือแม้แต่ merge เฉพาะชิ้นนั้นเป็นคอมมิตแยกได้
แม้แต่ stacked PR แบบปัจจุบันก็ยังปฏิบัติต่อ PR เหมือนเป็นหน่วยอะตอม สำหรับระบบส่วนใหญ่ PR ยังดูเป็นสิ่งที่หนักเกินไป
เหตุผลคือ “นั่นเป็นเพียงส่วนย่อยของไฟล์ จึงไม่รู้ว่าจะคอมไพล์ผ่านหรือไม่”
ผมไม่เห็นด้วยกับจุดยืนนั้นเลย แต่พออ่านคอมเมนต์นี้ก็ทำให้นึกถึงเรื่องนั้น เพราะถ้าจะทำอะไรแบบนี้ในเว็บวิวก็ต้องระวังมากพอสมควร
แน่นอนว่าไม่นับกรณีอย่างคอมเมนต์ข้างบนที่ถ้าเป็นเจ้าของรีโพซิทอรี ก็ force push เวอร์ชันที่ชอบเข้า branch ได้อยู่แล้ว
ต้องมี การตั้งค่า CI/CD แบบแทบไม่ต้องออกแรง
แค่มี
make build,make test,make uploadก็พอที่เหลือปล่อยไว้ใน makefile เพื่อให้ต่อยอดไปสู่ระบบบิลด์ที่ดีกว่าได้
ผมอยากไปจากไอเดียสู่ artifact ที่เผยแพร่ได้ภายใน 2 นาที
แทนที่จะใช้ไฟล์คอนฟิกในตำแหน่งที่รู้กันแบบที่ระบบ CI/CD ส่วนใหญ่ทำ ก็แค่วาง shell script 3 ตัวชื่อที่รู้กันไว้ในไดเรกทอรีที่รู้กัน
และถ้าต้องบิลด์บน Windows ก็ทำเป็นไฟล์
.batได้เป็นโบนัสมันอาจต่างกันไปตามระบบปฏิบัติการ และคุณอาจไม่อยากใส่มันไว้ใน makefile
ข้อดีคือทุกงานรันใน pty ของตัวเองใต้ zmx
คุณสามารถ attach เข้าไปที่งานที่ล้มเหลว แล้วกดลูกศรขึ้นกับ Enter เพื่อรันซ้ำได้
ผมอยากได้ security advisory ที่มี guardrail เพื่อให้ข้อมูลคุณภาพดีถูกเผยแพร่
ต้องมี ecosystem ที่ยึดคอมมิตเป็นศูนย์กลางเพื่อให้ทุกโปรเจ็กต์เผยแพร่ข้อมูลที่มีความหมายได้ และควรมี integration สำหรับโปรเจ็กต์ที่ต้องการออก CVE เองด้วย