แนวทางปฏิบัติที่ดีที่สุดในปัจจุบันสำหรับการจัดการหมายเลขรุ่นและหมายเลขเวอร์ชันอย่างเป็นระบบในโครงการ Java คืออะไร โดยเฉพาะ:
วิธีจัดการหมายเลขบิลด์อย่างเป็นระบบในสภาพแวดล้อมการพัฒนาแบบกระจาย
วิธีรักษาหมายเลขเวอร์ชันในซอร์ส / พร้อมใช้งานสำหรับแอปพลิเคชันรันไทม์
วิธีการรวมเข้ากับที่เก็บซอร์สอย่างถูกต้อง
วิธีจัดการหมายเลขเวอร์ชันเทียบกับแท็กที่เก็บโดยอัตโนมัติ
วิธีการรวมเข้ากับโครงสร้างพื้นฐานที่สร้างอย่างต่อเนื่อง
มีเครื่องมือจำนวนมากที่พร้อมใช้งานและ ant (ระบบสร้างที่เราใช้) มีงานที่จะรักษาหมายเลขบิลด์ไว้ แต่ยังไม่ชัดเจนว่าจะจัดการสิ่งนี้กับนักพัฒนาหลายคนพร้อมกันโดยใช้ CVS, svn หรือที่คล้ายกันได้อย่างไร .
[แก้ไข]
มีคำตอบบางส่วนหรือเฉพาะเจาะจงที่ดีและเป็นประโยชน์ปรากฏอยู่ด้านล่างดังนั้นฉันจะสรุปคำตอบบางส่วน สำหรับฉันดูเหมือนจะไม่มี "แนวทางปฏิบัติที่ดีที่สุด" ที่ชัดเจนในเรื่องนี้ แต่เป็นการรวบรวมแนวคิดที่ทับซ้อนกัน ด้านล่างนี้ค้นหาบทสรุปของฉันและคำถามที่เป็นผลลัพธ์บางอย่างที่ผู้คนอาจพยายามตอบเพื่อติดตามผล [ใหม่สำหรับ stackoverflow ... โปรดแสดงความคิดเห็นหากฉันทำสิ่งนี้ผิด]
หากคุณใช้ SVN การกำหนดเวอร์ชันของการชำระเงินที่เฉพาะเจาะจงจะมาพร้อมกับการโดยสาร การสร้างหมายเลขสามารถใช้ประโยชน์จากสิ่งนี้เพื่อสร้างหมายเลขบิวด์เฉพาะที่ระบุการชำระเงิน / การแก้ไขเฉพาะ [CVS ซึ่งเราใช้ด้วยเหตุผลเดิมไม่ได้ให้ข้อมูลเชิงลึกในระดับนี้มากนัก ... การแทรกแซงด้วยตนเองกับแท็กช่วยให้คุณมีส่วนร่วมได้]
หากคุณใช้ maven เป็นระบบบิลด์ของคุณจะมีการสนับสนุนสำหรับการสร้างหมายเลขเวอร์ชันจาก SCM รวมถึงโมดูลรีลีสสำหรับการสร้างรีลีสโดยอัตโนมัติ [เราไม่สามารถใช้ maven ได้ด้วยเหตุผลหลายประการ แต่สิ่งนี้จะช่วยผู้ที่ทำได้ [ขอบคุณmarcelo-morales ]]
หากคุณใช้antเป็นระบบบิลด์ของคุณคำอธิบายงานต่อไปนี้สามารถช่วยสร้างไฟล์ Java .properties ที่รวบรวมข้อมูลบิลด์ซึ่งสามารถพับลงในบิลด์ของคุณได้หลายวิธี [เราขยายความคิดนี้เพื่อรวมข้อมูลที่ได้มาจากฮัดสันขอบคุณmarty-lamb ]
Ant และ maven (และฮัดสันและระบบควบคุมความเร็วคงที่) ให้วิธีง่ายๆในการรับหมายเลขบิลด์ลงในไฟล์. คุณสมบัติหรือลงในไฟล์. txt / .html สิ่งนี้ "ปลอดภัย" เพียงพอที่จะป้องกันไม่ให้ถูกงัดแงะโดยตั้งใจหรือตั้งใจหรือไม่? การรวบรวมเป็นคลาส "กำหนดเวอร์ชัน" ในเวลาสร้างจะดีกว่าไหม
การยืนยัน: การสร้างหมายเลขควรกำหนด / บังคับใช้ในระบบการรวมแบบต่อเนื่องเช่นฮัดสัน [ขอบคุณmarcelo-morales ] เราได้รับข้อเสนอแนะนี้แล้ว แต่มันทำให้คำถามเกี่ยวกับวิศวกรรมการเปิดตัวแตก: การเปิดตัวเกิดขึ้นได้อย่างไร? มีหลายรุ่นในรุ่นหรือไม่? มีความสัมพันธ์ที่มีความหมายระหว่าง buildnumbers จากรีลีสที่แตกต่างกันหรือไม่?
คำถาม: อะไรคือวัตถุประสงค์ที่อยู่เบื้องหลังหมายเลขการสร้าง? ใช้สำหรับ QA หรือไม่? อย่างไร? มีการใช้โดยนักพัฒนาเพื่อแยกความคลุมเครือระหว่างหลาย ๆ บิลด์ระหว่างการพัฒนาหรือมากกว่าสำหรับ QA เพื่อพิจารณาว่าบิลด์ผู้ใช้ปลายทางได้รับอะไร หากเป้าหมายคือความสามารถในการทำซ้ำตามทฤษฎีแล้วนี่คือสิ่งที่หมายเลขเวอร์ชันรีลีสควรให้ - ทำไมถึงไม่ทำ (โปรดตอบสิ่งนี้เป็นส่วนหนึ่งของคำตอบของคุณด้านล่างนี้จะช่วยชี้ให้เห็นตัวเลือกที่คุณได้ทำ / แนะนำ ...
คำถาม: มีสถานที่สำหรับสร้างตัวเลขในการสร้างด้วยตนเองหรือไม่? นี่เป็นปัญหาที่ทุกคนควรใช้โซลูชัน CI หรือไม่?
คำถาม: ควรตรวจสอบหมายเลขบิลด์ใน SCM หรือไม่ หากเป้าหมายนั้นระบุโครงสร้างเฉพาะได้อย่างน่าเชื่อถือและไม่น่าสงสัยวิธีรับมือกับระบบการสร้างแบบต่อเนื่องหรือแบบแมนนวลที่อาจขัดข้อง / รีสตาร์ท / ฯลฯ ...
คำถาม: หมายเลขบิลด์ควรสั้นและไพเราะ (เช่นจำนวนเต็มที่เพิ่มขึ้นอย่างจำเจ) เพื่อให้ง่ายต่อการติดชื่อไฟล์สำหรับการจัดเก็บง่ายต่อการอ้างอิงในการสื่อสาร ฯลฯ ... หรือควรจะยาวและเต็มไปด้วยชื่อผู้ใช้ datestamps ชื่อเครื่อง ฯลฯ ?
คำถาม: โปรดระบุรายละเอียดเกี่ยวกับวิธีการกำหนดหมายเลขรุ่นที่เหมาะสมกับกระบวนการเผยแพร่อัตโนมัติที่ใหญ่กว่าของคุณ ใช่คนรัก maven เรารู้ว่ามันเสร็จแล้วและเสร็จแล้ว แต่พวกเราทุกคนยังไม่ได้ดื่ม kool-aid กันเลย ...
ฉันต้องการสรุปให้เป็นคำตอบที่สมบูรณ์อย่างน้อยก็สำหรับตัวอย่างที่เป็นรูปธรรมของการตั้งค่า cvs / ant / hudson ของเราดังนั้นใครบางคนสามารถสร้างกลยุทธ์ที่สมบูรณ์ตามคำถามนี้ได้ ฉันจะทำเครื่องหมายเป็น "คำตอบ" ทุกคนที่สามารถให้คำอธิบายแบบซุปต่อถั่วสำหรับกรณีนี้โดยเฉพาะ (รวมถึงรูปแบบการติดแท็ก cvs รายการกำหนดค่า CI ที่เกี่ยวข้องและขั้นตอนการเผยแพร่ที่พับหมายเลขบิลด์ลงในรีลีสเพื่อให้เป็นแบบทางโปรแกรม เข้าถึงได้) หากคุณต้องการถาม / ตอบสำหรับการกำหนดค่าอื่น ๆ (เช่น svn / maven / cruise control) ฉันจะเชื่อมโยงไปยังคำถามจากที่นี่ --JA
[แก้ไข 23 ต.ค. 52] ฉันยอมรับคำตอบที่ได้รับการโหวตสูงสุดเพราะคิดว่าเป็นวิธีแก้ปัญหาที่สมเหตุสมผลในขณะที่คำตอบอื่น ๆ ก็มีข้อคิดดีๆเช่นกัน ถ้ามีใครอยากจะแตกในการสังเคราะห์สิ่งเหล่านี้กับMarty-lambฉันจะพิจารณายอมรับอันอื่น ข้อกังวลเดียวที่ฉันมีกับ Marty-lamb คือมันไม่ได้สร้างหมายเลขบิลด์ที่ต่อเนื่องกันอย่างน่าเชื่อถือ - มันขึ้นอยู่กับนาฬิกาท้องถิ่นที่ระบบของผู้สร้างเพื่อให้หมายเลขการสร้างที่ไม่ชัดเจนซึ่งไม่ดี
[แก้ไข 10 ก.ค. ]
ตอนนี้เรารวมคลาสดังต่อไปนี้ ซึ่งทำให้สามารถรวบรวมหมายเลขเวอร์ชันลงในไฟล์ปฏิบัติการขั้นสุดท้ายได้ รูปแบบต่างๆของข้อมูลเวอร์ชันจะถูกปล่อยออกมาในข้อมูลการบันทึกผลิตภัณฑ์เอาต์พุตที่เก็บถาวรในระยะยาวและใช้เพื่อติดตามการวิเคราะห์ผลิตภัณฑ์เอาต์พุตของเรา (บางครั้งในปีต่อมา) ไปยังบิลด์เฉพาะ
public final class AppVersion
{
// SVN should fill this out with the latest tag when it's checked out.
private static final String APP_SVNURL_RAW =
"$HeadURL: svn+ssh://user@host/svnroot/app/trunk/src/AppVersion.java $";
private static final String APP_SVN_REVISION_RAW = "$Revision: 325 $";
private static final Pattern SVNBRANCH_PAT =
Pattern.compile("(branches|trunk|releases)\\/([\\w\\.\\-]+)\\/.*");
private static final String APP_SVNTAIL =
APP_SVNURL_RAW.replaceFirst(".*\\/svnroot\\/app\\/", "");
private static final String APP_BRANCHTAG;
private static final String APP_BRANCHTAG_NAME;
private static final String APP_SVNREVISION =
APP_SVN_REVISION_RAW.replaceAll("\\$Revision:\\s*","").replaceAll("\\s*\\$", "");
static {
Matcher m = SVNBRANCH_PAT.matcher(APP_SVNTAIL);
if (!m.matches()) {
APP_BRANCHTAG = "[Broken SVN Info]";
APP_BRANCHTAG_NAME = "[Broken SVN Info]";
} else {
APP_BRANCHTAG = m.group(1);
if (APP_BRANCHTAG.equals("trunk")) {
// this isn't necessary in this SO example, but it
// is since we don't call it trunk in the real case
APP_BRANCHTAG_NAME = "trunk";
} else {
APP_BRANCHTAG_NAME = m.group(2);
}
}
}
public static String tagOrBranchName()
{ return APP_BRANCHTAG_NAME; }
/** Answers a formatter String descriptor for the app version.
* @return version string */
public static String longStringVersion()
{ return "app "+tagOrBranchName()+" ("+
tagOrBranchName()+", svn revision="+svnRevision()+")"; }
public static String shortStringVersion()
{ return tagOrBranchName(); }
public static String svnVersion()
{ return APP_SVNURL_RAW; }
public static String svnRevision()
{ return APP_SVNREVISION; }
public static String svnBranchId()
{ return APP_BRANCHTAG + "/" + APP_BRANCHTAG_NAME; }
public static final String banner()
{
StringBuilder sb = new StringBuilder();
sb.append("\n----------------------------------------------------------------");
sb.append("\nApplication -- ");
sb.append(longStringVersion());
sb.append("\n----------------------------------------------------------------\n");
return sb.toString();
}
}
แสดงความคิดเห็นหากสิ่งนี้สมควรที่จะกลายเป็นการอภิปรายเกี่ยวกับวิกิ