การกระทำของ GitHub เพื่อดำเนินการวิเคราะห์แบบคงที่โดยใช้ CodeChecker เป็นไดรเวอร์ สำหรับโครงการ C-Family (C, C ++, Objective-C, CUDA ฯลฯ ), CodeChecker รองรับการขับเคลื่อนโปรแกรมการวิเคราะห์แบบคงที่ของ Clang เอาต์พุตของเครื่องวิเคราะห์แบบคงที่อื่น ๆ สามารถรวมเข้ากับ codeChecker ผ่านตัวแปลงรายงาน
สคริปต์คอมโพสิตแอคชั่นเดียวนี้ครอบคลุมขั้นตอนต่อไปนี้:
หมายเหตุ: การวิเคราะห์แบบคงที่อาจเป็นกระบวนการใช้เวลานาน ขอแนะนำว่าขั้นตอนการวิเคราะห์แบบคงที่ไม่ได้เป็นลำดับกับการดำเนินการ CI ที่เหลือ แต่ทำงานเป็นงานของตัวเองในเวิร์กโฟลว์หรือเวิร์กโฟลว์ที่แตกต่างอย่างสิ้นเชิง
โปรดตรวจสอบให้แน่ใจว่าโครงการของคุณได้รับการกำหนดค่าอย่างสมบูรณ์สำหรับการสร้างก่อนดำเนินการดำเนินการนี้
หมายเหตุ: เครื่องวิเคราะห์แบบคงที่สามารถพึ่งพาข้อมูลเพิ่มเติมที่ได้รับการปรับให้เหมาะสมในการสร้างรีลีสที่แท้จริง ดังนั้นขอแนะนำให้กำหนดค่าโครงการของคุณในการกำหนดค่า Debug
เพิ่มงานลงใน CI ของคุณดังนี้ ทั้งสองเวอร์ชันเป็นเอกสิทธิ์เฉพาะบุคคล - คุณสามารถให้ฐานข้อมูลการรวบรวมหรือคุณสั่งให้ CodeChecker สร้างหนึ่ง
บางโครงการมีความสำคัญเพียงพอในการกำหนดค่าการสร้างของพวกเขาซึ่งไม่จำเป็นต้องดำเนินการเพิ่มเติมหลังจากดำเนินการ configure.sh , cmake หรือเครื่องมือที่คล้ายกัน หากคุณสามารถสร้าง ฐานข้อมูลการรวบรวม จากระบบบิลด์ของคุณ โดยไม่ต้อง ใช้งานสร้างเองคุณสามารถประหยัดเวลาและไปที่การวิเคราะห์ได้ทันที
คุณสามารถระบุฐานข้อมูลการรวบรวมที่สร้างขึ้นในตัวแปร logfile
job :
steps :
# Check YOUR project out!
- name : " Check out repository "
uses : actions/checkout@v2
# Prepare a build
- name : " Prepare build "
run : |
mkdir -pv Build
cd Build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
# Run the analysis
- uses : whisperity/codechecker-analysis-action@v1
id : codechecker
with :
logfile : ${{ github.workspace }}/Build/compile_commands.json
# Upload the results to the CI.
- uses : actions/upload-artifact@v2
with :
name : " CodeChecker Bug Reports "
path : ${{ steps.codechecker.outputs.result-html-dir }} โครงการประเภทอื่นอาจพึ่งพา รหัสที่สร้างขึ้น อย่างมาก เมื่อดูที่ซอร์สโค้ดของโครงการเหล่านี้ โดยไม่มี การสร้างที่ถูกดำเนินการล่วงหน้าพวกเขาไม่ได้รวบรวม - เช่นนี้การวิเคราะห์ไม่สามารถดำเนินการได้เช่นกัน
ในกรณีนี้คุณจะต้องสั่งให้ CodeChecker เข้าสู่ระบบบิลด์ (และใช้เวลาในการสร้าง) ก่อนการวิเคราะห์
คุณสามารถระบุการสร้างเพื่อดำเนินการในตัวแปรบิล build-command
job :
steps :
# Check YOUR project out!
- name : " Check out repository "
uses : actions/checkout@v2
# Prepare a build
- name : " Prepare build "
run : |
mkdir -pv Build
cd Build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF
# Run the analysis
- uses : whisperity/codechecker-analysis-action@v1
id : codechecker
with :
build-command : " cd ${{ github.workspace }}/Build; cmake --build . "
# Upload the results to the CI.
- uses : actions/upload-artifact@v2
with :
name : " CodeChecker Bug Reports "
path : ${{ steps.codechecker.outputs.result-html-dir }} หากมีการร้องขอตัวแปรเอาท์พุท warnings สามารถจับคู่กับการดำเนินการขั้นตอนในงานที่ทำลายงานทั้งหมดหากโครงการคำเตือนการวิเคราะห์ ใด ๆ ถูกปล่อยออกมา
หมายเหตุ: เนื่องจากการวิเคราะห์แบบคงที่อาจมีเสียงดังและรายงานที่ไม่สามารถแก้ไขได้พฤติกรรมเริ่มต้นและคำแนะนำคือการรายงานผลการวิจัยเท่านั้น แต่ไม่ทำลาย CI ทั้งหมด
เพื่อให้ได้รายงานในรูปแบบที่มนุษย์ใช้เวลานานพวกเขาจะต้องอัปโหลดที่ไหนสักแห่งก่อนที่ขั้นตอนความล้มเหลวจะล้มเหลวตลอดงาน!
job :
steps :
# Check YOUR project out!
- name : " Check out repository "
uses : actions/checkout@v2
# Prepare a build
- name : " Prepare build "
run : |
mkdir -pv Build
cd Build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF
# Run the analysis
- uses : whisperity/codechecker-analysis-action@v1
id : codechecker
with :
build-command : " cd ${{ github.workspace }}/Build; cmake --build . "
# Upload the results to the CI.
- uses : actions/upload-artifact@v2
with :
name : " CodeChecker Bug Reports "
path : ${{ steps.codechecker.outputs.result-html-dir }}
# Break the build if there are *ANY* warnings emitted by the analysers.
- name : " Break build if CodeChecker reported any findings "
if : ${{ steps.codechecker.outputs.warnings == 'true' }}
run : exit 1หากโครงการของคุณโฮสต์เซิร์ฟเวอร์ CodeChecker ที่ไหนสักแห่งสามารถกำหนดค่างานเพื่อสร้างหรืออัปเดตการรันโดยอัตโนมัติ
# It is recommended that storing only happens for PUSH events, and preferably
# only for long-term branches.
on :
push :
job :
steps :
# Check YOUR project out!
- name : " Check out repository "
uses : actions/checkout@v2
# Prepare a build
- name : " Prepare build "
run : |
mkdir -pv Build
cd Build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF
# Run the analysis
- uses : whisperity/codechecker-analysis-action@v1
id : codechecker
with :
build-command : " cd ${{ github.workspace }}/Build; cmake --build . "
store : true
store-url : ' http://example.com:8001/MyProject '
store-username : ${{ secrets.CODECHECKER_STORE_USER }}
store-password : ${{ secrets.CODECHECKER_STORE_PASSWORD }}
# store-run-name: "custom run name to store against"CodeChecker มีความสามารถในการคำนวณความแตกต่างระหว่างการวิเคราะห์สองครั้ง หากการวิเคราะห์รุ่นที่เสถียรของโครงการถูกเก็บไว้ (ดูด้านบน) ไปยังเซิร์ฟเวอร์งานสำหรับคำขอดึงสามารถกำหนดค่าที่ปฏิเสธคำขอดึงโดยอัตโนมัติหากพยายามแนะนำผลการวิเคราะห์ ใหม่
เพื่อให้ได้รายงานในรูปแบบที่มนุษย์ใช้เวลานานพวกเขาจะต้องอัปโหลดที่ไหนสักแห่งก่อนที่ขั้นตอนความล้มเหลวจะล้มเหลวตลอดงาน!
on :
pull_request :
runs :
steps :
# Check the pull request out! (In pull_request jobs, the checkout action
# automatically downloads the "after-merge" state of the pull request if
# there are no conflicts.)
- name : " Check out repository "
uses : actions/checkout@v2
# Prepare a build
- name : " Prepare build "
run : |
mkdir -pv Build
cd Build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=OFF
# Run the analysis
- uses : whisperity/codechecker-analysis-action@v1
id : codechecker
with :
build-command : " cd ${{ github.workspace }}/Build; cmake --build . "
store : ${{ github.event_name == 'push' }}
store-url : ' http://example.com:8001/MyProject '
store-username : ${{ secrets.CODECHECKER_STORE_USER }}
store-password : ${{ secrets.CODECHECKER_STORE_PASSWORD }}
# Keep the names for 'store' and 'diff' in sync, or auto-generated!
# diff-run-name: "custom run name to store with"
diff : ${{ github.event_name == 'pull_request' }}
diff-url : ' http://example.com:8001/MyProject '
diff-username : ${{ secrets.CODECHECKER_DIFF_USER }}
diff-password : ${{ secrets.CODECHECKER_DIFF_PASSWORD }}
# diff-run-name: "custom run name to diff against"
# Upload the potential new findings results to the CI.
- uses : actions/upload-artifact@v2
if : ${{ steps.codechecker.outputs.warnings-in-diff == 'true' }}
with :
name : " New introduced results Bug Reports "
path : ${{ steps.codechecker.outputs.diff-html-dir }}
- name : " Fail the job if new findings are introduced "
if : ${{ steps.codechecker.outputs.warnings-in-diff == 'true' }}
shell : bash
run : |
echo "::error title=New static analysis warnings::Analysed commit would introduce new static analysis warnings and potential bugs to the project"
# Fail the build, after results were collected and uploaded.
exit 1 สคริปต์คอมโพสิตแอคชั่นเดียวนี้ครอบคลุมขั้นตอนต่อไปนี้:
report-converter เพื่อแปลงรายงานของเครื่องวิเคราะห์อื่นเป็นรูปแบบของ CodeCheckerหมายเหตุ: การวิเคราะห์แบบคงที่อาจเป็นกระบวนการใช้เวลานาน ขอแนะนำว่าขั้นตอนการวิเคราะห์แบบคงที่ไม่ได้เป็นลำดับกับการดำเนินการ CI ที่เหลือ แต่ทำงานเป็นงานของตัวเองในเวิร์กโฟลว์หรือเวิร์กโฟลว์ที่แตกต่างอย่างสิ้นเชิง
โปรดดูเอกสารประกอบของตัวเลือกที่คุณเลือกสำหรับสิ่งนี้ CodeChecker ไม่ สนับสนุนการขับเคลื่อนการวิเคราะห์ผ่านเครื่องมือภายนอก แต่หากการวิเคราะห์ที่ประสบความสำเร็จเสร็จสิ้นมันสามารถแปลงและจัดเก็บผลลัพธ์
job :
steps :
# Check YOUR project out!
- name : " Check out repository "
uses : actions/checkout@v2
# Perform the analysis. Details vary between analysers!
# Example for "PyLint" added below!
- name : " Analyse with PyLint "
run : |
sudo apt-get -y install pylint
pylint -f json --exit-zero myproject > pylint_reports.json
# Run the conversion
- uses : whisperity/codechecker-analysis-action@v1
id : codechecker
with :
report-converter : true
original-analyser : " pylint "
original-analysis-output : " pylint_reports.json "
# Upload the results (after conversion by CodeChecker) to the CI.
- uses : actions/upload-artifact@v2
with :
name : " CodeChecker Bug Reports "
path : ${{ steps.codechecker.outputs.result-html-dir }}เครื่องมือ รายงานคอนเวอร์เตอร์ แปลงเอาต์พุตของเครื่องวิเคราะห์ต่างๆเป็นรูปแบบทั่วไปที่ใช้โดย CodeChecker เมื่อการแปลงเสร็จสิ้นคุณสมบัติที่เหลือของแอ็คชั่นสามารถดำเนินการในแบบเดียวกับโครงการ C/C ++ โปรดดูส่วนก่อนหน้าของเอกสารสำหรับการกำหนดค่าของคุณสมบัติเหล่านี้
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
config | $(project-root)/.codechecker.json | ไฟล์การกำหนดค่าที่มีธงที่จะผนวกเข้ากับคำสั่งการวิเคราะห์ ขอแนะนำว่าการกำหนดค่าการวิเคราะห์ส่วนใหญ่จะถูกกำหนดขึ้นด้วยโครงการ - อ่านเพิ่มเติมเกี่ยวกับไฟล์การกำหนดค่า codechecker.json ในเอกสารอย่างเป็นทางการ |
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
llvm-version | latest | LLVM เวอร์ชันหลักในการติดตั้งและใช้งาน LLVM ติดตั้งจาก PPA ชุมชน ค่า จะต้อง เป็นรุ่นหลัก (เช่น 13 ) ที่สนับสนุนโดย PPA สำหรับระบบปฏิบัติการที่ใช้! หาก latest ให้รวบรวมเวอร์ชันล่าสุด (ยังไม่เผยแพร่) โดยอัตโนมัติ หาก ignore อย่าติดตั้งอะไรเลย (ไม่แนะนำ) |
install-custom | false | หากตั้งค่าเป็น true เปิดความสามารถในการโคลนในพื้นที่และติดตั้ง codeChecker จาก repository และ version ที่ระบุ มิฉะนั้น version จะถูกนำมาเป็นเวอร์ชันรุ่นและดาวน์โหลด CodeChecker Suite จาก PYPI |
repository | Ericsson/CodeChecker | ที่เก็บ CodeChecker เพื่อตรวจสอบและสร้างหาก install-custom เป็น true |
version | master | หาก install-custom เป็น false เวอร์ชันรุ่น (เช่น 6.18.0 ) เพื่อดาวน์โหลดจาก PYPI หรือ master เพื่อรับรุ่นล่าสุด มิฉะนั้นสาขา (การผิดนัดเป็นต้น master ), แท็กหรือกระทำ sha ใน repository เพื่อตรวจสอบ |
- อ่านเพิ่มเติมเกี่ยวกับ CodeChecker log ในเอกสารอย่างเป็นทางการ
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
logfile | ตำแหน่งของฐานข้อมูลการรวบรวม JSON ซึ่งอธิบายถึงวิธีการสร้างโครงการ การตั้งค่าสถานะนี้จะใช้หากระบบบิลด์สามารถสร้างไฟล์ให้เราล่วงหน้าได้ | |
build-command | คำสั่ง build เพื่อดำเนินการ CodeChecker มีความสามารถในการดำเนินการและบันทึกการสร้างด้วยตัวเอง ธงนี้ใช้หากระบบบิลด์ไม่สามารถสร้างข้อมูลด้วยตัวเองหรือโครงการอาศัยรหัสที่สร้างขึ้นอื่น ๆ |
- อ่านเพิ่มเติมเกี่ยวกับ CodeChecker analyze ในเอกสารอย่างเป็นทางการ
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
analyze-output | (สร้างอัตโนมัติ) | ไดเรกทอรีที่ควรเก็บเอาต์พุตการวิเคราะห์ ดิบ |
ctu | false | เปิดใช้งานการวิเคราะห์หน่วยการแปลข้ามใน เครื่องวิเคราะห์แบบคงที่ |
ignore-analyze-crashes | true | หากตั้งค่าเป็น true ขั้นตอนการวิเคราะห์จะไม่รายงานข้อผิดพลาดหากการวิเคราะห์บางอย่างล้มเหลว (เนื่องจากความผิดพลาดที่อาจเกิดขึ้นในเสียงดัง) |
- อ่านเพิ่มเติมเกี่ยวกับ CodeChecker parse ในเอกสารอย่างเป็นทางการ
- อ่านเพิ่มเติมเกี่ยวกับ report-converter ในเอกสารอย่างเป็นทางการ
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
report-converter | false | หากตั้งค่าเป็น true งานจะดำเนิน การแปลงรายงาน จากเครื่องวิเคราะห์อื่น ๆ แทนที่จะขับเคลื่อนการวิเคราะห์แบบคงที่ด้วยตัวเอง |
original-analyser | "ประเภท" ของการวิเคราะห์ที่ ดำเนินการ ก่อนหน้านี้ ส่งผ่านเป็นอินพุตบังคับไปยัง Consultable report-converter | |
original-analysis-output | ไฟล์หรือไดเรกทอรีที่ผลลัพธ์ของตัววิเคราะห์บุคคลที่สามมีอยู่ ส่งผ่านเป็นอินพุตบังคับไปยัง Consultable report-converter |
- อ่านเพิ่มเติมเกี่ยวกับ CodeChecker cmd diff ในเอกสารอย่างเป็นทางการ
- การตรวจสอบผลการวิเคราะห์กับเนื้อหาของเซิร์ฟเวอร์ต้องได้รับอนุญาต PRODUCT_VIEW หากเซิร์ฟเวอร์ต้องการการรับรองความถูกต้อง
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
diff | false | หากตั้งค่าเป็น true งานจะคำนวณความแตกต่างของผลการวิเคราะห์ปัจจุบันกับผลลัพธ์ที่เก็บไว้ในเซิร์ฟเวอร์ระยะไกล |
diff-url | URL ของผลิตภัณฑ์ CodeChecker เพื่อตรวจสอบและแตกต่าง รวมถึง จุดสิ้นสุด มักจะอยู่ในรูปแบบของ http://example.com/ProductName การระบุตัวแปรนี้เป็น สิ่งจำเป็น หากตั้งค่า diff เป็น true | |
diff-username | หากเซิร์ฟเวอร์ต้องการการตรวจสอบสิทธิ์ในการเข้าถึงให้ระบุชื่อผู้ใช้ที่เช็คควรเข้าสู่ระบบด้วย | |
diff-password | รหัสผ่านหรือโทเค็นการเข้าถึงที่สร้างขึ้นซึ่งสอดคล้องกับผู้ใช้ - หมายเหตุ: ขอแนะนำว่าสิ่งนี้ได้รับการกำหนดค่าเป็นความลับที่เก็บและให้เช่น: ${{ secrets.CODECHECKER_PASSWORD }} เมื่อกำหนดค่าการกระทำ | |
diff-run-name | (สร้างอัตโนมัติในรูปแบบ user/repo: branchname ) | การดำเนินการวิเคราะห์ CodeChecker จะถูกรวบรวมเป็น วิ่ง การวิ่งมักจะสัมพันธ์กับการกำหนดค่าเดียวของการวิเคราะห์ |
- อ่านเพิ่มเติมเกี่ยวกับ CodeChecker store ในเอกสารอย่างเป็นทางการ
- การจัดเก็บการรันไปยังเซิร์ฟเวอร์ต้องได้รับอนุญาต PRODUCT_STORE หากเซิร์ฟเวอร์ต้องการการตรวจสอบสิทธิ์
| ตัวแปร | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|
store | false | หากตั้งค่าเป็น true สคริปต์จะอัปโหลดการค้นพบไปยังเซิร์ฟเวอร์ CodeChecker โดยปกติแล้วธงอื่น ๆ จะต้องมีการกำหนดค่าด้วย! |
store-url | URL ของผลิตภัณฑ์ CodeChecker ที่จะจัดเก็บ รวมถึง จุดสิ้นสุด มักจะอยู่ในรูปแบบของ http://example.com/ProductName การระบุตัวแปรนี้เป็น สิ่งจำเป็น หากตั้งค่า store เป็น true | |
store-username | หากเซิร์ฟเวอร์ต้องการการตรวจสอบสิทธิ์ในการเข้าถึงให้ระบุชื่อผู้ใช้ที่การอัปโหลดควรเข้าสู่ระบบด้วย | |
store-password | รหัสผ่านหรือโทเค็นการเข้าถึงที่สร้างขึ้นซึ่งสอดคล้องกับผู้ใช้ - หมายเหตุ: ขอแนะนำว่าสิ่งนี้ได้รับการกำหนดค่าเป็นความลับที่เก็บและให้เช่น: ${{ secrets.CODECHECKER_PASSWORD }} เมื่อกำหนดค่าการกระทำ | |
store-run-name | (สร้างอัตโนมัติในรูปแบบ user/repo: branchname ) | การดำเนินการวิเคราะห์ CodeChecker จะถูกรวบรวมเป็น วิ่ง การวิ่งมักจะสัมพันธ์กับการกำหนดค่าเดียวของการวิเคราะห์ การรันสามารถเก็บไว้ได้เพิ่มขึ้นซึ่งกรณี CodeChecker สามารถใส่คำอธิบายประกอบได้ว่ารายงานได้รับการแก้ไขแล้ว |
outputs การดำเนินการเพื่อใช้ในขั้นตอนต่อไปการกระทำจะเปิดเผยผลลัพธ์ต่อไปนี้ซึ่งอาจใช้ในขั้นตอนของเวิร์กโฟลว์ที่ประสบความสำเร็จในการวิเคราะห์
| ตัวแปร | ค่า | คำอธิบาย |
|---|---|---|
analyze-output | อินพุตที่สร้างอัตโนมัติหรือ analyze-output | ไดเรกทอรีที่มีไฟล์เอาต์พุตการวิเคราะห์ แบบดิบ (สร้างโดยเครื่องวิเคราะห์หรือตัวแปลง) |
codechecker-version | สร้างอัตโนมัติ (น่าจะเหมือนกับ version ) | เวอร์ชันของ codeChecker ที่ติดตั้งซึ่งทำการวิเคราะห์ |
codechecker-hash | สร้างอัตโนมัติ | แฮช git ของ codechecker ที่ติดตั้งซึ่งทำการวิเคราะห์ |
logfile | อินพุตที่สร้างอัตโนมัติหรือ logfile | ฐานข้อมูลการรวบรวม JSON ของการวิเคราะห์ที่ดำเนินการ |
llvm-version | สร้างอัตโนมัติ | สตริงเวอร์ชันเต็มของแพ็คเกจ LLVM/Clang ที่ติดตั้ง (ตามรายงานโดย clang --version ) |
diff-html-dir | สร้างอัตโนมัติ | ไดเรกทอรีที่รายงานข้อผิดพลาด HTML ที่ใช้งานง่าย ถูกสร้างขึ้นเกี่ยวกับการค้นพบ ใหม่ (หากเปิดใช้งาน diff ) |
diff-result-log | สร้างอัตโนมัติ | ไฟล์บันทึกเอาต์พุตของ CodeChecker cmd diff ซึ่งมีการค้นพบ ใหม่ ที่ถูกทิ้งลงไป |
diff-run-name | อินพุตที่สร้างโดยอัตโนมัติหรือ diff-run-name | ชื่อของการวิเคราะห์การทำงาน (ถ้าเปิดใช้ diff ) กับรายงานที่ถูกเปรียบเทียบ |
result-html-dir | สร้างอัตโนมัติ | ไดเรกทอรีที่มีการสร้างรายงานข้อผิดพลาด HTML ที่ใช้งานง่าย |
result-log | สร้างอัตโนมัติ | ไฟล์บันทึกเอาต์พุตของ CodeChecker parse ซึ่งมีการค้นพบที่ถูกทิ้งลงไป |
store-run-name | อินพุตที่สร้างโดยอัตโนมัติหรือ store-run-name | ชื่อของการวิเคราะห์การทำงาน (หากเปิดใช้งาน store ) ซึ่งผลลัพธ์ถูกอัปโหลดไปยัง |
store-successful | true หรือ false | การจัดเก็บผลลัพธ์จะสำเร็จหรือไม่ มีประโยชน์สำหรับการเลือกโครงสร้างในภายหลังเพื่อตรวจจับความล้มเหลวของเครือข่าย |
warnings | true หรือ false | ไม่ว่าจะเป็นเครื่องวิเคราะห์แบบคงที่รายงานการค้นพบใด ๆ |
warnings-in-diff | true หรือ false | หากเปิดใช้งาน diff ไม่ว่าจะมีการค้นพบ ใหม่ ในการวิเคราะห์ปัจจุบันเมื่อเปรียบเทียบกับเนื้อหาของเซิร์ฟเวอร์ |