การทำงานอัตโนมัติสำหรับการเผยแพร่รุ่น
รุ่นของ Libre WebUI ถูกสร้างจากราก repository ด้วยสคริปต์ release สคริปต์จะอ่านประวัติ git จริงนับจากแท็กเวอร์ชันก่อนหน้า อัปเดตเวอร์ชันแพ็กเกจ เขียน changelog รันการตรวจ release, commit รุ่น และสร้างแท็กเวอร์ชัน GitHub เป็นแหล่ง build และเผยแพร่ไฟล์ไบนารี ส่วน metadata ของรุ่นและลิงก์ artifact ที่ตั้งชื่อไว้จะถูก mirror ไปยัง repository Forgejo ของโครงการ
การตั้งค่าในเครื่องครั้งแรก
ติดตั้ง dependency และเปิด hook ของ repository:
npm install
npm run setup-hooks
การตั้งค่า hook จะกำหนด:
.githooks/commit-msgสำหรับตรวจ Conventional Commit.githooks/pre-commitสำหรับตรวจการจัดรูปแบบ.gitmessageเป็นเทมเพลตข้อความ commit ในเครื่อง
สร้างรุ่น
รันสคริปต์ release จาก worktree ที่สะอาดบนสาขาที่ต้องการติดแท็ก:
# Patch release
npm run release
# Minor release
npm run release:minor
# Major release
npm run release:major
สคริปต์จะทำโดยอัตโนมัติ:
- ตรวจว่า working tree สะอาดและแท็กในเครื่องถัดไปยังว่าง
- รวบรวมหลักฐานจาก commit, ไฟล์, dependency, locale และ changelog ที่ยังไม่เผยแพร่
- สร้าง release notes จากหลักฐานนั้น
- อัปเดต
package.json, ไฟล์แพ็กเกจ workspace,package-lock.json, เวอร์ชัน chart และแอปของ Helm รวมถึงCHANGELOG.md - รัน
npm run release:checkซึ่งรวมการจัดรูปแบบ, lint, build, การทดสอบ, security audit และการจำลอง publish npm - เมื่อการตรวจทั้งหมดผ่านเท่านั้น จึง commit รุ่นและสร้างแท็กเวอร์ชันแบบ annotated
การสร้าง Changelog
ดูตัวอย่างส่วน changelog ถัดไปโดยไม่แก้ไฟล์:
npm run changelog
อัปเดต CHANGELOG.md ด้วยส่วนที่สร้างขึ้น:
npm run changelog -- update
ตามค่าเริ่มต้น การสร้าง changelog สามารถขอร่างที่ขัดเกลาจากโมเดลที่เข้ากันได้กับ Ollama ในเครื่อง แล้วตรวจผลลัพธ์เทียบกับหลักฐาน git ที่รวบรวม หาก AI ใช้ไม่ได้หรือผลลัพธ์ดูไม่ปลอดภัย สคริปต์จะใช้ตัวสร้างแบบกำหนดผลแน่นอนแทน
ค่า override ที่มีประโยชน์:
CHANGELOG_AI=0 npm run release:minor
CHANGELOG_AI_MODEL=glm-5.2:cloud npm run changelog
OLLAMA_BASE_URL=http://127.0.0.1:11434 npm run release
Push รุ่น
หลังสร้าง release commit และ annotated tag แล้ว ให้เผยแพร่เฉพาะ commit ของสาขาและแท็กที่สคริปต์แสดง สาขาระบบใช้งานจริงจะ push ไป Forgejo ก่อน แล้วจึง GitHub พร้อมปิดการตามแท็กอย่างชัดเจน:
git -c push.followTags=false push \
https://git.kroonen.ai/libre-webui/libre-webui.git \
HEAD:refs/heads/main
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
refs/heads/main
git -c push.followTags=false push \
https://github.com/libre-webui/libre-webui.git \
HEAD:refs/heads/main
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
refs/heads/main
SHA ของสาขาที่ทั้งสองบริการส่งกลับต้องตรงกับ local release commit ที่ตั้งใจไว้ รอให้ workflow GitHub ที่จำเป็นสำหรับ commit นั้นผ่านก่อนเผยแพร่แท็ก
ยืนยันว่าแท็กเวอร์ชันยังไม่มีในทั้งสองบริการ แล้ว push แท็กนั้นเพียงแท็กเดียวไป Forgejo ก่อนและ GitHub ทีหลัง:
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git -c push.followTags=false push \
https://git.kroonen.ai/libre-webui/libre-webui.git \
refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
git -c push.followTags=false push \
https://github.com/libre-webui/libre-webui.git \
refs/tags/vX.Y.Z:refs/tags/vX.Y.Z
git ls-remote \
https://git.kroonen.ai/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
git ls-remote \
https://github.com/libre-webui/libre-webui.git \
'refs/tags/vX.Y.Z' 'refs/tags/vX.Y.Z^{}'
แทน vX.Y.Z ด้วยแท็ก release สำหรับ annotated tag ให้ตรวจทั้ง SHA ของ tag object และ SHA ของ peeled commit ห้ามใช้ git push --tags เพราะอาจเผยแพร่แท็กในเครื่องที่ไม่เกี่ยวข้อง
เส้นทาง Release ใน CI
การ push แท็ก v* จะรัน workflow release บน GitHub โดย workflow จะ:
- รัน
npm run release:check - build artifact Electron สำหรับ macOS, Windows และ Linux
- สร้าง GitHub release จากส่วน
CHANGELOG.mdที่ตรงกัน - mirror ระเบียนรุ่นและลิงก์ artifact ที่ตั้งชื่อไว้ไป Forgejo
- build Docker image
- เผยแพร่ Helm chart ด้วยเวอร์ชันเดียวกับแท็ก release
- เผยแพร่แพ็กเกจ npm ด้วย
NPM_TOKEN
สามารถรันการตรวจเดียวกันในเครื่องก่อนติดแท็ก:
npm run release:check
Mirror รุ่นไป Forgejo
การ mirror ใช้ personal access token ของ Forgejo ซึ่งเก็บเป็น secret ที่เข้ารหัสใน GitHub Actions ชื่อ FORGEJO_TOKEN ให้ token มีเฉพาะ scope write:repository, ตรวจว่าเจ้าของเขียนไปยัง libre-webui/libre-webui ได้ และห้าม commit หรือพิมพ์ token
การ mirror ถูกออกแบบให้รันซ้ำได้อย่างปลอดภัย โดยค้นหารุ่นจากแท็ก สร้างเฉพาะระเบียนรุ่นที่ขาด ปรับ metadata ให้ตรงกับ GitHub release และข้ามลิงก์ artifact ที่มีอยู่แล้ว ดังนั้นการลองใหม่หลังปัญหาเครือข่ายหรือ workflow จะเติมงานที่ขาดโดยไม่สร้าง release หรือ asset ซ้ำ
asset ของรุ่นบน Forgejo เป็นลิงก์ภายนอกที่มีชื่อไปยัง browser_download_url สาธารณะของ GitHub GitHub ยังคงเป็นโฮสต์ไฟล์ไบนารี ขณะที่ Forgejo แสดงชื่อไฟล์ดาวน์โหลดเดียวกันโดยไม่ทำซ้ำ artifact แอปเดสก์ท็อปหลายสิบกิกะไบต์ source archive ยังถูกสร้างแยกจากแท็กเดียวกันบนแต่ละบริการ
ดูตัวอย่างหรือเติมรุ่นหนึ่งรายการ
ตรวจสิ่งที่จะเปลี่ยนโดยไม่เขียนไป Forgejo:
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z --dry-run
หลังโหลด FORGEJO_TOKEN และ GITHUB_TOKEN จากตัวจัดการ secret ของผู้ดูแลเข้าสู่สภาพแวดล้อมโปรเซส ให้ mirror รุ่นนั้น:
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z
แท็กที่ระบุต้องมีอยู่แล้วบน GitHub และ Forgejo และชี้ไปยัง tag object กับ peeled commit เดียวกันก่อนจะ mirror รุ่น
ดูตัวอย่างหรือเติมทุกรุ่น
ตรวจสอบ GitHub Release ทุกอันเทียบกับ Forgejo:
node scripts/mirror-forgejo-releases.mjs --all --dry-run
เติม Forgejo Release ที่ขาดหรือไม่สมบูรณ์ทั้งหมด:
node scripts/mirror-forgejo-releases.mjs --all
ต้องใช้ GITHUB_TOKEN สำหรับ --all รวมถึง dry run เพราะการตรวจความเท่ากันของแท็กและการค้นหา asset ต้องส่งคำขอมากกว่าขีดจำกัด API แบบไม่ระบุตัวตนของ GitHub และต้องใช้ FORGEJO_TOKEN เพิ่มเมื่อไม่ได้ใช้ --dry-run
เส้นทาง --all แบ่งหน้าทั้งสอง API และพิจารณาเฉพาะออบเจ็กต์ GitHub Release ไม่ใช่ทุก Git tag แท็กที่ตั้งใจไม่มี GitHub Release จะยังเป็นเพียงแท็กบน Forgejo รัน dry run อีกครั้งหลังเติมข้อมูล ซึ่งควรรายงานว่าไม่มีการเปลี่ยนแปลงค้างอยู่
นโยบายแท็กที่เปลี่ยนแปลงไม่ได้
แท็กเวอร์ชันที่เผยแพร่แล้วเปลี่ยนแปลงไม่ได้ หลังแท็กมีอยู่บน remote ใด ๆ:
- ห้ามลบ
- ห้าม force-push
- ห้ามย้ายไปยัง commit ที่แก้ไขแล้ว
- ห้ามใช้ semantic version เดิมกับเนื้อหาอื่น
หากเนื้อหารุ่นที่เผยแพร่ผิด ให้แก้ source และ changelog แล้วเผยแพร่ patch version ถัดไป หากขาดเพียงหน้า release หรือลิงก์ asset ภายนอก ให้รัน mirror ที่ทำซ้ำได้อีกครั้งโดยไม่แตะแท็ก
แท็ก v0.8.6 บน Forgejo เคยได้รับการจัดแนวใหม่เพียงครั้งเดียวโดยอนุมัติอย่างชัดเจนระหว่างเริ่มใช้การ mirror สองระบบ การย้ายที่ผ่านการตรวจสอบนั้นแก้ tag object ประวัติศาสตร์สองรายการซึ่งอธิบาย source tree เดียวกันแต่สืบจากสาย commit ต่างกัน เหตุการณ์นี้ไม่ใช่แบบอย่างสำหรับการย้ายแท็กที่เผยแพร่แล้ว
นโยบายเวอร์ชัน Helm
ค่า version ของ Helm chart, appVersion ของ chart, เวอร์ชันแพ็กเกจราก และแท็ก release ตั้งใจใช้ semantic version เดียวกัน สคริปต์ release จะเลื่อนพร้อมกัน และ CI ปฏิเสธเมื่อไม่ตรงกัน
chart เผยแพร่จากแท็ก release v* ที่เปลี่ยนแปลงไม่ได้เท่านั้น ห้ามเผยแพร่เนื้อหา chart ที่แก้ไขภายใต้เวอร์ชัน chart เดิม การเปลี่ยน chart ต้องผ่าน application release ถัดไปเพื่อรับเวอร์ชันใหม่
chart เวอร์ชัน 0.14.1 มี digest override แบบครั้งเดียว เพราะรุ่นนั้นเก่ากว่า semantic Docker tag ค่า digest ระบุ image หลายสถาปัตยกรรม 0.14.1 ที่ตรวจสอบแล้ว สคริปต์ release จะล้าง override นี้เมื่อสร้างรุ่นถัดไป จากนั้น image เริ่มต้นจะอ้างอิง appVersion ของ chart
workflow Docker เผยแพร่แท็ก semantic-version นั้นไปยัง GHCR และ Docker Hub จากแท็ก release v* เดียวกัน การเผยแพร่ Helm จะรอสูงสุด 20 นาทีให้ image Docker Hub สาธารณะที่ตรงกัน และจะล้มเหลวแทนการเผยแพร่ chart ที่ไม่มี image เริ่มต้น ส่วน image Ollama ที่รวมมาด้วยกำหนดค่าแยกและใช้แท็ก latest ของต้นทางเป็นค่าเริ่มต้น
Conventional Commits
ข้อความ commit ควรใช้รูปแบบ Conventional Commit:
<type>[optional scope]: <description>
ชนิดที่พบบ่อย:
feat: ฟีเจอร์สำหรับผู้ใช้fix: แก้บั๊กdocs: อัปเดตเอกสารrefactor: ปรับโครงสร้างโค้ดภายในperf: ปรับประสิทธิภาพtest: ความครอบคลุมการทดสอบchore: งานบำรุงรักษา release หรือ build
การเปลี่ยนแปลงที่ไม่เข้ากันใช้ !:
git commit -m "feat!: remove deprecated endpoint"
git commit -m "fix(auth)!: change token validation"
การแก้ปัญหา
Working directory ไม่สะอาด
commit หรือ stash การเปลี่ยนแปลงในเครื่องก่อนเผยแพร่:
git status --short
git add .
git commit -m "fix: resolve pending changes"
ไม่มีการเปลี่ยนแปลงที่เผยแพร่ได้
ตรวจ commit นับจากแท็กก่อนหน้า:
git log $(git describe --tags --abbrev=0)..HEAD --oneline
Changelog ต้องแก้ด้วยตนเอง
แก้ CHANGELOG.md แล้ว commit การแก้ก่อนเผยแพร่แท็ก:
git add CHANGELOG.md
git commit -m "docs: refine changelog"
ย้อน local release commit
หากยังไม่ได้ push release commit หรือแท็ก:
git tag -d v0.12.0
git reset --soft HEAD~1
หาก remote ใดมีแท็กแล้ว ห้ามลบหรือแทนที่ ให้แก้ปัญหาบน main, สร้าง patch release ถัดไป และเผยแพร่แท็กใหม่ที่เปลี่ยนแปลงไม่ได้ผ่านด่านทั้งหมด
Mirror Forgejo ไม่สมบูรณ์
ก่อนอื่นยืนยันว่า SHA ของ remote tag object และ peeled commit ตรงกัน จากนั้นดูตัวอย่างและลองรุ่นที่ได้รับผลกระทบใหม่:
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z --dry-run
node scripts/mirror-forgejo-releases.mjs --tag vX.Y.Z
ข้อผิดพลาดการอนุญาตหมายถึง FORGEJO_TOKEN ขาด หมดอายุ เป็นของผู้ใช้ที่ไม่มีสิทธิ์ repository หรือไม่มี write:repository ส่วนแท็ก remote ที่ขาดหรือต่างต้องตรวจแยก เพราะ release mirror จะไม่สร้างหรือย้าย Git tag
ไฟล์สำหรับผู้ดูแล
.gitmessage- เทมเพลตข้อความ commit.githooks/commit-msg- ตรวจ Conventional Commit.githooks/pre-commit- ตรวจการจัดรูปแบบล่วงหน้าscripts/release.js- การประสาน releasescripts/mirror-forgejo-releases.mjs- mirror และ backfill รุ่น Forgejo ที่ทำซ้ำได้scripts/generate-changelog.js- คำสั่งดูตัวอย่าง/อัปเดต changelogscripts/lib/releaseNotes.js- รวบรวมหลักฐานและสร้าง changelog.github/workflows/release.yml- workflow CI release ที่ขับเคลื่อนด้วยแท็ก.github/workflows/helm-publish.yml- ตรวจ Helm และเผยแพร่แท็ก
อ่านข้อมูลเพิ่มเติมเกี่ยวกับ Conventional Commits ได้ที่ https://www.conventionalcommits.org/