Bạn xử lý các tệp cấu hình trong kiểm soát nguồn như thế nào?


96

Giả sử bạn có một ứng dụng web điển hình và có cấu hình tệp. Tùy chọn. Mỗi nhà phát triển làm việc trong dự án sẽ có một phiên bản cho hộp phát triển của họ, sẽ có một phiên bản dành cho nhà phát triển, sản phẩm và giai đoạn. Làm thế nào để bạn đối phó với điều này trong kiểm soát nguồn? Không kiểm tra tệp này ở tất cả, kiểm tra nó với các tên khác nhau hoặc làm một cái gì đó yêu thích hoàn toàn?

Câu trả lời:


69

Những gì tôi đã làm trước đây là có một tệp cấu hình mặc định được đăng ký để kiểm soát nguồn. Sau đó, mỗi nhà phát triển có tệp cấu hình ghi đè của riêng họ được loại trừ khỏi kiểm soát nguồn. Trước tiên, ứng dụng sẽ tải tệp mặc định, sau đó nếu tệp ghi đè xuất hiện, hãy tải tệp đó và sử dụng bất kỳ cài đặt nào từ tệp ghi đè tùy chọn sang tệp mặc định.

Nói chung, tệp ghi đè càng nhỏ càng tốt, nhưng nó luôn có thể chứa nhiều cài đặt hơn cho một nhà phát triển có môi trường không chuẩn.


24

Cấu hình mã, và bạn nên phiên bản nó. Chúng tôi đặt các tệp cấu hình của mình dựa trên tên người dùng; trong cả UNIX / Mac và Windows, bạn có thể truy cập vào tên đăng nhập của người dùng, và miễn là chúng là duy nhất cho dự án, bạn vẫn ổn. Bạn thậm chí có thể ghi đè điều này trong môi trường, nhưng bạn nên kiểm soát phiên bản của mọi thứ.

Điều này cũng cho phép bạn kiểm tra cấu hình của những người khác, có thể giúp chẩn đoán các vấn đề về xây dựng và nền tảng.


10
1 hoàn toàn cho nhấn mạnh cấu hình mà vẫn nên được phiên bản
Alexander Bird

Và nếu tên người dùng không đáng tin cậy vì bất kỳ lý do gì, thì bạn có thể có một tệp duy nhất chỉ có một dòng cung cấp tên của tệp cấu hình ghi đè. Bằng cách này, có rất ít (khoảng 10 ký tự hoặc hơn) không được kiểm soát phiên bản. Và tệp README có thể giải thích rằng bạn cần tạo tệp đó.
Alexander Bird

Tôi luôn nghĩ rằng các cấu hình nên được giữ riêng biệt với mã. Tôi đã làm việc ở những nơi yêu cầu quá nhiều cấu hình cho một repo mà Git chỉ bị quá tải với các tệp cấu hình. Không nói rằng cấu hình không nên được tạo phiên bản, chúng thuộc về nơi khác giống như một trình quản lý tạo tác. Cấu hình không phải là mã, chúng là cài đặt cho mã.
Thomas

Tệp cấu hình có thể chứa thông tin nhạy cảm như mật khẩu không được tạo phiên bản. Hay bạn muốn cấp cho mọi nhà phát triển quyền truy cập vào môi trường sản xuất của bạn? Tôi nghĩ tốt hơn là chỉ tạo phiên bản một "cấu hình chính" và ghi đè nó trong các môi trường cụ thể.
Christophe Weis,

19

Không phiên bản tệp đó. Phiên bản một mẫu hoặc một cái gì đó.


2
Tôi sử dụng cách tiếp cận này, tôi chỉ có một main.php.tmpl và khi tôi kiểm tra một bản sao mới, chỉ cần sao chép nó vào main, php. Tôi thêm tệp main.php vào danh sách bỏ qua để tránh tình cờ xác nhận nó.
levhita

10

Nhóm của tôi giữ các phiên bản riêng biệt của tệp cấu hình cho từng môi trường (web.config.dev, web.config.test, web.config.prod). Các tập lệnh triển khai của chúng tôi sao chép phiên bản chính xác, đổi tên thành web.config. Bằng cách này, chúng tôi có toàn quyền kiểm soát phiên bản trên các tệp cấu hình cho từng môi trường, có thể dễ dàng thực hiện khác biệt, v.v.


6

Hiện tại, tôi có tệp cấu hình "mẫu" với một phần mở rộng được thêm vào, ví dụ:

web.config.rename

Tuy nhiên, tôi có thể thấy vấn đề với phương pháp này nếu các thay đổi quan trọng đã thay đổi.


6

+1 về phương pháp tiếp cận mẫu.

Nhưng vì câu hỏi này có gắn thẻ Git, nên các giải pháp thay thế được phân phối xuất hiện trong tâm trí, trong đó các tùy chỉnh được lưu giữ trên một nhánh thử nghiệm riêng:

A---B---C---D---           <- mainline (public)
     \       \
      B'------D'---        <- testing (private)

Trong lược đồ này, dòng chính chứa tệp cấu hình chung, "mẫu" yêu cầu số lượng điều chỉnh tối thiểu để trở nên hoạt động.

Giờ đây, các nhà phát triển / người kiểm tra có thể chỉnh sửa tệp cấu hình cho phù hợp với nội dung của họ và chỉ cam kết những thay đổi này cục bộ trên một nhánh kiểm tra riêng (ví dụ: B '= B + tùy chỉnh). Mỗi khi đường chính tiến bộ, họ dễ dàng hợp nhất nó vào thử nghiệm, dẫn đến các cam kết hợp nhất chẳng hạn như D '(= D + phiên bản hợp nhất của các tùy chỉnh của B).

Lược đồ này thực sự tỏa sáng khi tệp cấu hình "mẫu" được cập nhật: các thay đổi từ cả hai bên được hợp nhất và rất có thể dẫn đến xung đột (hoặc lỗi kiểm tra) nếu chúng không tương thích!


Nhưng khi các nhà phát triển thử nghiệm đẩy vào dòng chính, các thay đổi của họ đối với tệp mẫu cũng sẽ được đẩy vào. Không?
Nick Zalutskiy

Trừ khi có một giải pháp cho nhận xét của Nick, điều này sẽ không hoạt động từ những gì tôi thấy. Hoặc có thể giải thích mô hình luồng bạn đang sử dụng sẽ giải quyết được vấn đề.
Alexander Bird

Tôi đồng ý với cách tiếp cận mẫu với bất kỳ điều chỉnh cần thiết nào được đưa vào tại thời điểm xây dựng. Tuy nhiên về chủ đề phân nhánh ... Điều gì sẽ xảy ra nếu có nhiều mẫu (dev, test, v.v.) và các nhà phát triển chỉ cần bỏ qua các thay đổi khỏi cam kết của họ. Không dễ dàng nhưng có thể làm việc với sự hợp tác.
NickSuperb

5

Giải pháp chúng tôi sử dụng là chỉ có một tệp cấu hình duy nhất (web.config / app.config), nhưng chúng tôi thêm một phần đặc biệt vào tệp chứa cài đặt cho tất cả các môi trường.

Có một ĐỊA PHƯƠNG, DEV, QA, SẢN XUẤT chứa các khóa cấu hình liên quan đến môi trường đó trong (các) tệp cấu hình của chúng tôi.

Điều làm cho tất cả điều này hoạt động là một lắp ráp có tên xxx. được tham chiếu trong tất cả các ứng dụng của chúng tôi (winforms và webforms) cho ứng dụng biết nó đang hoạt động trên môi trường nào.

Hợp ngữ xxx.Enosystem đọc một dòng thông tin từ machine.config của máy nhất định cho biết rằng nó đang ở trên DEV, QA, v.v. Mục này có trên tất cả các máy trạm và máy chủ của chúng tôi.

Hi vọng điêu nay co ich.


1
Này hoạt động rất tốt nếu chỉ có một vài sự khác biệt giữa môi trường (dây kết nối tức)
Eric Labashosky

và giả sử không có 100s của các nhà phát triển tất cả các thiết lập tùy chỉnh đặt họ ở đó cũng như (nó sẽ vẫn làm việc, nhưng sẽ rất cồng kềnh)
Alexander Bird

5

Tôi luôn giữ tất cả các phiên bản của tệp cấu hình trong kiểm soát nguồn, trong cùng thư mục với tệp web.config.

Ví dụ

web.config
web.qa.config
web.staging.config
web.production.config

Tôi thích quy ước đặt tên này hơn (trái ngược với web.config.production hoặc production.web.config) vì

  • Nó giữ các tệp lại với nhau khi bạn sắp xếp theo tên tệp
  • Nó giữ các tệp lại với nhau khi bạn sắp xếp theo phần mở rộng tệp
  • Nếu tệp vô tình được đẩy sang phiên bản sản xuất, bạn sẽ không thể xem nội dung qua http vì IIS sẽ ngăn các tệp * .config được phân phát

Tệp cấu hình mặc định phải được định cấu hình để bạn có thể chạy ứng dụng cục bộ trên máy của mình.

Quan trọng nhất, các tệp này phải gần như giống nhau 100% ở mọi khía cạnh, ngay cả định dạng. Bạn không nên sử dụng các tab trong một phiên bản và khoảng trắng trong một phiên bản khác để thụt lề. Bạn sẽ có thể chạy một công cụ khác biệt đối với các tệp để xem chính xác điểm khác biệt giữa chúng. Tôi thích sử dụng WinMerge để khác biệt các tệp.

Khi quy trình xây dựng của bạn tạo các tệp nhị phân, sẽ có một tác vụ ghi đè web.config bằng tệp cấu hình thích hợp cho môi trường đó. Nếu các tệp được nén, thì các tệp không liên quan sẽ bị xóa khỏi bản dựng đó.


4

Tôi đã sử dụng mẫu trước đây, tức là web.dev.config, web.prod.config, v.v., nhưng bây giờ thích kỹ thuật 'ghi đè tệp' hơn. Tệp web.config chứa phần lớn cài đặt, nhưng tệp bên ngoài chứa các giá trị dành riêng cho môi trường như kết nối db. Lời giải thích hay trên blog của Paul Wilson .

Tôi nghĩ rằng điều này làm giảm số lượng trùng lặp giữa các tệp cấu hình có thể gây đau khi thêm các giá trị / thuộc tính mới.


3

@Grant nói đúng.

Tôi thuộc một nhóm với gần 100 nhà phát triển khác và các tệp cấu hình của chúng tôi không được kiểm soát nguồn. Chúng tôi có các phiên bản của tệp trong kho lưu trữ được kéo ra mỗi lần kiểm tra nhưng chúng không thay đổi.

Nó đã làm việc khá tốt cho chúng tôi.


2

Phiên bản của tôi kiểm soát nó, nhưng không bao giờ đẩy nó sang các máy chủ khác. Nếu máy chủ sản xuất yêu cầu thay đổi, tôi thực hiện thay đổi đó trực tiếp vào tệp cấu hình.

Nó có thể không đẹp, nhưng nó hoạt động tốt.


2

Phiên bản app / web.config đã đăng ký, đơn giản phải đủ chung để hoạt động trên tất cả các máy của nhà phát triển và luôn được cập nhật với bất kỳ thay đổi cài đặt mới nào, v.v. Nếu bạn yêu cầu một bộ cài đặt cụ thể cho nhà phát triển / test / production settings, kiểm tra các tệp riêng biệt với các cài đặt đó, như GateKiller đã nêu, với một số loại quy ước đặt tên, mặc dù tôi thường sử dụng "web.prod.config", vì không thay đổi phần mở rộng tệp.


2

Chúng tôi sử dụng tệp cấu hình mẫu được đăng ký để kiểm soát phiên bản và sau đó là một bước trong bản dựng tự động của chúng tôi để thay thế các mục nhập cụ thể trong tệp mẫu bằng cài đặt dành riêng cho môi trường. Các cài đặt dành riêng cho môi trường được lưu trữ trong một tệp XML riêng biệt cũng nằm dưới sự kiểm soát của phiên bản.

Chúng tôi đang sử dụng MSBuild trong bản dựng tự động của mình, vì vậy chúng tôi sử dụng tác vụ XmlUpdate từ Tác vụ cộng đồng MSBuild để cập nhật các giá trị.


2

Trong một thời gian dài, tôi đã làm đúng những gì bcwood đã làm. Tôi giữ các bản sao của web.dev.config, web.test.config, web.prod.config, v.v. dưới quyền kiểm soát nguồn và sau đó hệ thống xây dựng / triển khai của tôi tự động đổi tên chúng khi nó triển khai đến các môi trường khác nhau. Bạn nhận được một lượng dư thừa nhất định giữa các tệp (đặc biệt là với tất cả các nội dung của asp.net trong đó), nhưng nói chung nó hoạt động rất tốt. Bạn cũng phải đảm bảo rằng mọi người trong nhóm nhớ cập nhật tất cả các tệp khi họ thực hiện thay đổi.

Nhân tiện, tôi muốn giữ ".config" ở cuối làm phần mở rộng để các liên kết tệp không bị phá vỡ.

Đối với các phiên bản dành cho nhà phát triển cục bộ của tệp cấu hình, tôi luôn cố gắng hết sức để khuyến khích mọi người sử dụng cùng một cài đặt cục bộ càng nhiều càng tốt để không cần phải có phiên bản của riêng bạn. Nó không phải lúc nào cũng hoạt động với tất cả mọi người, trong trường hợp đó, mọi người thường chỉ thay thế nó cục bộ khi cần thiết và đi từ đó. Nó không quá đau đớn hay bất cứ điều gì.


1

Trong dự án của chúng tôi, chúng tôi có cấu hình được lưu trữ trong các tệp có tiền tố, sau đó hệ thống xây dựng của chúng tôi đưa vào cấu hình thích hợp dựa trên tên máy chủ của hệ thống hiện tại. Điều này hoạt động tốt đối với chúng tôi trong một nhóm tương đối nhỏ, cho phép chúng tôi áp dụng các thay đổi cấu hình cho tệp của người khác nếu / khi chúng tôi thêm một mục cấu hình mới. Rõ ràng điều này chắc chắn không quy mô cho các dự án mã nguồn mở với số lượng nhà phát triển không giới hạn.


1

Chúng tôi có hai vấn đề ở đây.

  • Đầu tiên chúng ta phải kiểm soát tệp cấu hình được gửi cùng với phần mềm.

    Tất cả đều dễ dàng để nhà phát triển kiểm tra một sự thay đổi không mong muốn đối với tệp cấu hình chính, nếu họ đang sử dụng cùng một tệp trong môi trường phát triển.

    Mặt khác, nếu bạn có một tệp cấu hình riêng được trình cài đặt bao gồm, bạn rất dễ quên thêm một cài đặt mới vào nó hoặc để các nhận xét trong đó không đồng bộ với các nhận xét trong bản phát triển. tập tin cấu hình.

  • Sau đó, chúng tôi gặp vấn đề là các nhà phát triển phải giữ cho bản sao của tệp cấu hình được cập nhật khi các nhà phát triển khác thêm cài đặt cấu hình mới. Tuy nhiên, một số cài đặt như chuỗi kết nối cơ sở dữ liệu là khác nhau đối với mỗi nhà phát triển.

  • Có một vấn đề thứ 3 mà câu hỏi / câu trả lời không đề cập đến. Làm cách nào để bạn hợp nhất những thay đổi mà khách hàng đã thực hiện đối với tệp cấu hình của bạn khi bạn cài đặt phiên bản phần mềm mới?

Tôi vẫn chưa thấy giải pháp tốt nào hoạt động tốt trong mọi trường hợp, tuy nhiên tôi đã thấy một số giải pháp từng phần (có thể được kết hợp trong các kết hợp khác nhau nếu cần) làm giảm vấn đề đi rất nhiều.

  • Trước hết hãy giảm số lượng mục cấu hình bạn có trong tệp cấu hình chính của mình.

    Nếu bạn không cần cho phép khách hàng thay đổi ánh xạ của mình, hãy sử dụng Fluent NHibernate (hoặc cách khác) để chuyển cấu hình thành mã.

    Tương tự như vậy đối với thiết lập tiêm cạn kiệt.

  • Tách tệp cấu hình khi có thể, ví dụ: sử dụng tệp riêng biệt để định cấu hình những gì Log4Net ghi lại.

  • Không lặp lại các mục giữa nhiều tệp cấu hình, ví dụ: nếu bạn có 4 ứng dụng web được cài đặt trên cùng một máy, hãy có tệp cấu hình tổng thể mà tệp web.config trong mỗi ứng dụng trỏ đến.

    (Sử dụng đường dẫn tương đối theo mặc định, vì vậy hiếm khi phải thay đổi tệp web.config)

  • Xử lý tệp cấu hình phát triển để nhận tệp cấu hình vận chuyển.

    Điều này có thể được thực hiện bằng cách có các giá trị mặc định trong các nhận xét Xml sau đó được đặt trong tệp cấu hình khi quá trình xây dựng hoàn tất. Hoặc có các phần bị xóa như một phần của quá trình tạo trình cài đặt.

  • Thay vì chỉ có một chuỗi kết nối cơ sở dữ liệu, hãy có một chuỗi cho mỗi nhà phát triển.

    Ví dụ: trước tiên hãy tìm “database_ianr” (trong đó ianr là tên người dùng hoặc tên máy của tôi) trong tệp cấu hình tại thời điểm chạy, nếu không tìm thấy thì hãy tìm “database”

    Có cấp độ thứ 2 "ví dụ -oracle hoặc -sqlserver" giúp các nhà phát triển truy cập cả hai hệ thống cơ sở dữ liệu nhanh hơn.

    Điều này tất nhiên cũng có thể được thực hiện cho bất kỳ giá trị cấu hình nào khác.

    Sau đó, tất cả các giá trị kết thúc bằng “_userName” có thể được xóa trước khi gửi tệp cấu hình.

Tuy nhiên, cuối cùng thì bạn là “chủ sở hữu của tệp cấu hình” có trách nhiệm quản lý (các) tệp cấu hình như trên hay cách khác. Anh / cô ấy cũng nên thực hiện một sự khác biệt trên tệp cấu hình giao diện khách hàng trước mỗi chuyến hàng.

Bạn không thể loại bỏ nhu cầu về một người chăm sóc trong một số vấn đề khó khăn này.


1

Tôi không nghĩ rằng có một giải pháp duy nhất phù hợp với mọi trường hợp vì nó có thể phụ thuộc vào độ nhạy của dữ liệu trong các tệp cấu hình, hoặc ngôn ngữ lập trình bạn đang sử dụng và nhiều yếu tố khác. Nhưng tôi nghĩ điều quan trọng là phải giữ các tệp cấu hình cho tất cả các môi trường dưới quyền kiểm soát nguồn, vì vậy bạn luôn có thể biết khi nào nó được thay đổi và bởi ai, và quan trọng hơn là có thể khôi phục nó nếu có sự cố. Và họ sẽ làm.

Vì vậy, đây là cách tôi làm điều đó. Điều này thường dành cho các dự án nodejs nhưng tôi nghĩ nó cũng hoạt động cho các khung và ngôn ngữ khác.

Những gì tôi làm là tạo một configsthư mục tại thư mục gốc của dự án và trong thư mục đó giữ nhiều tệp cho tất cả các môi trường (và đôi khi các tệp riêng biệt cho môi trường của mỗi nhà phát triển) đều được theo dõi trong kiểm soát nguồn. Và có tệp thực tế mà mã sử dụng được đặt tên configở thư mục gốc của dự án. Đây là tệp duy nhất không được theo dõi. Vì vậy, nó trông như thế này

root
|
|- config (not tracked)
|
|- configs/ (all tracked)
    |- development
    |- staging
    |- live
    |- James

Khi ai đó kiểm tra dự án, anh ta sao chép tệp cấu hình mà anh ta muốn sử dụng vào configtệp không được kiểm tra và anh ta có thể tự do chỉnh sửa nó theo ý muốn nhưng cũng có trách nhiệm sao chép những thay đổi này trước khi chuyển sang các tệp môi trường khác nếu cần.

Và trên các máy chủ, tệp không được theo dõi có thể đơn giản là bản sao (hoặc tham chiếu) của tệp được theo dõi tương ứng với môi trường đó. Trong JS, bạn chỉ cần có 1 dòng để yêu cầu tệp đó.

Luồng này lúc đầu có thể hơi phức tạp nhưng nó có những ưu điểm tuyệt vời: 1. Bạn không bao giờ phải lo lắng về việc tệp cấu hình bị xóa hoặc sửa đổi trên máy chủ mà không có bản sao lưu 2. Điều tương tự nếu nhà phát triển có một số cấu hình tùy chỉnh trên máy và máy của anh ta ngừng hoạt động vì bất kỳ lý do gì 3. Trước khi triển khai, bạn có thể khác biệt các tệp cấu hình cho developmentstagingví dụ, và xem liệu có gì bị thiếu hoặc bị hỏng không.


0

Chúng tôi chỉ giữ cho tệp cấu hình sản xuất được đăng ký. Nhà phát triển có trách nhiệm thay đổi tệp khi họ lấy tệp ra khỏi nguồn an toàn cho quá trình dàn dựng hoặc phát triển. Điều này đã khiến chúng tôi bị thiêu rụi trong quá khứ nên tôi sẽ không đề xuất nó.


0

Tôi đã đối mặt với vấn đề tương tự và tôi đã tìm ra giải pháp cho nó. Đầu tiên tôi đã thêm tất cả các tệp vào kho lưu trữ trung tâm (cũng là các tệp của nhà phát triển).

Vì vậy, nếu một nhà phát triển tìm nạp các tệp từ kho lưu trữ, cấu hình nhà phát triển cũng ở đó. Khi thay đổi được thực hiện đối với tệp này, Git không nên biết về những thay đổi này. Bằng cách đó, các thay đổi không thể được đẩy / cam kết vào kho lưu trữ mà vẫn ở cục bộ.

Tôi giải quyết điều này bằng cách sử dụng lệnh git: update-index --assume-unchanged. Tôi đã tạo một tệp dơi được thực thi trong bản dựng trước của các dự án có chứa tệp mà các thay đổi sẽ bị Git bỏ qua. Đây là mã tôi đặt trong tệp bat:

IF NOT EXIST %2%\.git GOTO NOGIT
set fileName=%1
set fileName=%fileName:\=/%
for /f "useback tokens=*" %%a in ('%fileName%') do set fileName=%%~a
set "gitUpdate=git update-index --assume-unchanged"
set parameter= "%gitUpdate% %fileName%"
echo %parameter% as parameter for git
"C:\Program Files (x86)\Git\bin\sh.exe" --login -i -c %parameter%
echo Make FIleBehaveLikeUnchangedForGit Done.
GOTO END
:NOGIT
echo no git here.
echo %2%
:END

Trong bản dựng trước của mình, tôi sẽ thực hiện một cuộc gọi đến tệp dơi, ví dụ:

call "$(ProjectDir)\..\..\MakeFileBehaveLikeUnchangedForGit.bat" "$(ProjectDir)Web.config.developer" "$(SolutionDir)"

Tôi đã tìm thấy trên SO một tệp bat sao chép tệp cấu hình chính xác vào web.config / app.config. Tôi cũng gọi đây là tệp dơi trong bản dựng sẵn. Mã cho tệp dơi này là:

@echo off
echo Comparing two files: %1 with %2
if not exist %1 goto File1NotFound
if not exist %2 goto File2NotFound
fc %1 %2 
if %ERRORLEVEL%==0 GOTO NoCopy
echo Files are not the same.  Copying %1 over %2
copy %1 %2 /y & goto END
:NoCopy
echo Files are the same.  Did nothing
goto END
:File1NotFound
echo %1 not found.
goto END
:File2NotFound
copy %1 %2 /y
goto END
:END
echo Done.

Trong bản dựng trước của mình, tôi sẽ thực hiện một cuộc gọi đến tệp dơi, ví dụ:

call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.