Pergunta

Digamos que você tenha um aplicativo web típico e com um arquivo configuration.whatever.Cada desenvolvedor trabalhando no projeto terá uma versão para suas caixas de desenvolvimento, haverá versões dev, prod e stage.Como você lida com isso no controle de origem?Não fez check-in deste arquivo, verificou-o com nomes diferentes ou fez algo totalmente sofisticado?

Foi útil?

Solução

O que fiz no passado foi ter um arquivo de configuração padrão que foi verificado no controle de origem.Então, cada desenvolvedor tem seu próprio arquivo de configuração de substituição, que é excluído do controle de origem.O aplicativo primeiro carrega o padrão e, em seguida, se o arquivo de substituição estiver presente, carrega-o e usa quaisquer configurações da substituição em preferência ao arquivo padrão.

Em geral, quanto menor o arquivo de substituição melhor, mas ele sempre pode conter mais configurações para um desenvolvedor com um ambiente muito fora do padrão.

Outras dicas

Não versione esse arquivo.Versão de um modelo ou algo assim.

Configuração é código, e você deve versioná-lo.Baseamos nossos arquivos de configuração em nomes de usuário;tanto no UNIX/Mac quanto no Windows você pode acessar o nome de login do usuário e, desde que sejam exclusivos do projeto, tudo bem.Você pode até substituir isso no ambiente, mas você deve controle de versão tudo.

Isso também permite examinar as configurações de outras pessoas, o que pode ajudar a diagnosticar problemas de construção e plataforma.

Minha equipe mantém versões separadas dos arquivos de configuração para cada ambiente (web.config.dev, web.config.test, web.config.prod).Nossos scripts de implantação copiam a versão correta, renomeando-a para web.config.Dessa forma, temos controle total de versão dos arquivos de configuração de cada ambiente, podemos facilmente realizar uma comparação, etc.

Atualmente tenho o arquivo de configuração "template" com uma extensão adicionada, por exemplo:

web.config.rename

No entanto, posso ver um problema com esse método se alterações críticas forem alteradas.

A solução que usamos é ter apenas um único arquivo de configuração (web.config/app.config), mas adicionamos uma seção especial ao arquivo que contém configurações para todos os ambientes.

Existe um LOCAL, DEV, QA, PRODUÇÃO seções, cada uma contendo as chaves de configuração relevantes para esse ambiente em nosso(s) arquivo(s) de configuração.

O que faz tudo isso funcionar é uma montagem chamada xxx.Ambiente que é referenciado em todos os nossos aplicativos (winforms e webforms), que informa ao aplicativo em qual ambiente ele está operando.

O assembly xxx.Environment lê uma única linha de informações do máquina.config da máquina fornecida, que informa que está em DEV, QA, etc.Esta entrada está presente em todas as nossas estações de trabalho e servidores.

Espero que isto ajude.

+1 na abordagem do modelo.

Mas como essa pergunta tem tag git, a alteração alternativa distribuída, na qual as personalizações são mantidas em uma filial de testes privados:

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

Nesse esquema, a linha principal contém um arquivo de configuração "modelo" genérico que exige a quantidade mínima de ajustes para se tornar funcional.

Agora, desenvolvedores/testadores podem ajustar o arquivo de configuração para o conteúdo de seu coração e apenas cometer essas alterações localmente em uma ramificação de testes privados (por exemplo,B' = B + personalizações).Cada vez que os avanços da linha principal, eles o mesclam sem esforço em testes, o que resulta em cometidos de mesclagem, como d '(= d + versão mesclada das personalizações de B).

Este esquema realmente brilha quando o arquivo de configuração do "modelo" é atualizado:As mudanças de ambos os lados são mescladas e são extremamente propensas a resultar em conflitos (ou falhas de teste) se forem incompatíveis!

Eu usei o modelo antes, ou seja,web.dev.config, web.prod.config, etc, mas agora prefira a técnica de 'substituir arquivo'.O arquivo web.config contém a maioria das configurações, mas um arquivo externo contém valores específicos do ambiente, como conexões de banco de dados.Boa explicação sobre Blog de Paul Wilson.

Acho que isso reduz a quantidade de duplicação entre os arquivos de configuração, o que pode causar problemas ao adicionar novos valores/atributos.

Sempre mantive todas as versões dos arquivos de configuração no controle de origem, na mesma pasta do arquivo web.config.

Por exemplo

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

Eu prefiro esta convenção de nomenclatura (em oposição a web.config.production ou production.web.config) porque

  • Ele mantém os arquivos juntos quando você classifica por nome de arquivo
  • Ele mantém os arquivos juntos quando você classifica por extensão de arquivo
  • Se o arquivo for enviado acidentalmente para produção, você não poderá ver o conteúdo por http porque o IIS impedirá que arquivos *.config sejam veiculados

O arquivo de configuração padrão deve ser configurado de forma que você possa executar o aplicativo localmente em sua própria máquina.

Mais importante ainda, esses arquivos devem ser quase 100% idênticos em todos os aspectos, até mesmo na formatação.Você não deve usar tabulações em uma versão e espaços em outra para recuo.Você deve ser capaz de executar uma ferramenta de comparação nos arquivos para ver exatamente o que há de diferente entre eles.Eu prefiro usar o WinMerge para diferenciar os arquivos.

Quando o seu processo de construção cria os binários, deve haver uma tarefa que substitui o web.config pelo arquivo de configuração apropriado para esse ambiente.Se os arquivos estiverem compactados, os arquivos não relevantes deverão ser excluídos dessa compilação.

@Grant está certo.

Estou em uma equipe com cerca de 100 outros desenvolvedores e nossos arquivos de configuração não são verificados no controle de origem.Temos versões dos arquivos no repositório que são extraídas a cada check-out, mas elas não mudam.

Funcionou muito bem para nós.

Eu o controlo de versão, mas nunca o empurro para outros servidores.Se o servidor de produção exigir uma alteração, faço essa alteração diretamente no arquivo de configuração.

Pode não ser bonito, mas funciona muito bem.

A versão simples e simples de check-in de app/web.config deve ser genérica o suficiente para funcionar em todas as máquinas de desenvolvedores e ser mantida atualizada com quaisquer novas alterações de configuração, etc.Se você precisar de um conjunto específico de configurações para configurações de desenvolvimento/teste/produção, verifique arquivos separados com essas configurações, como afirmou o GateKiller, com algum tipo de convenção de nomenclatura, embora eu normalmente use "web.prod.config", como não para alterar a extensão do arquivo.

Usamos um arquivo de configuração de modelo que é verificado no controle de versão e, em seguida, uma etapa em nossa construção automatizada para substituir entradas específicas no arquivo de modelo por configurações específicas do ambiente.As configurações específicas do ambiente são armazenadas em um arquivo XML separado que também está sob controle de versão.

Estamos usando o MSBuild em nossa compilação automatizada, por isso usamos a tarefa XmlUpdate de Tarefas da comunidade MSBuild para atualizar os valores.

Por muito tempo, fiz exatamente o que bcwood fez.Eu mantenho cópias de web.dev.config, web.test.config, web.prod.config, etc.sob controle de origem e, em seguida, meu sistema de construção/implantação os renomeia automaticamente à medida que é implantado em vários ambientes.Você obtém uma certa redundância entre os arquivos (especialmente com todo o material do asp.net), mas geralmente funciona muito bem.Você também precisa garantir que todos na equipe se lembrem de atualizar todos os arquivos quando eles fazem uma alteração.

A propósito, gosto de manter ".config" no final como extensão para que as associações de arquivos não sejam quebradas.

No que diz respeito às versões do arquivo de configuração para desenvolvedores locais, sempre tento o meu melhor para encorajar as pessoas a usarem as mesmas configurações locais tanto quanto possível, para que não haja necessidade de ter sua própria versão.Nem sempre funciona para todos; nesse caso, as pessoas geralmente apenas o substituem localmente conforme necessário e partem daí.Não é muito doloroso nem nada.

Em nosso projeto, temos a configuração armazenada em arquivos com um prefixo, então nosso sistema de compilação obtém a configuração apropriada com base no nome de host do sistema atual.Isso funciona bem para nós em uma equipe relativamente pequena, permitindo-nos aplicar alterações de configuração aos arquivos de outras pessoas se/quando adicionarmos um novo item de configuração.Obviamente, isso definitivamente não se adapta a projetos de código aberto com um número ilimitado de desenvolvedores.

Temos dois problemas aqui.

  • Primeiramente temos que controlar o arquivo de configuração que acompanha o software.

    É fácil para um desenvolvedor fazer check-in de uma alteração indesejada no arquivo de configuração mestre, se eles estiverem usando o mesmo arquivo no ambiente de devolução.

    Por outro lado, se você tiver um arquivo de configuração separado incluído pelo instalador, é muito fácil esquecer de adicionar uma nova configuração a ele ou deixar os comentários nele contidos ficarem fora de sincronia com os comentários na devolução. arquivo de configuração.

  • Então temos o problema de que os desenvolvedores precisam manter sua cópia do arquivo de configuração atualizada enquanto outros desenvolvedores adicionam novas definições de configuração.No entanto, algumas configurações, como cadeias de conexão de banco de dados, são diferentes para cada desenvolvedor.

  • Há um terceiro problema que as perguntas/respostas não cobrem. Como você mescla as alterações que um cliente fez em seu arquivo de configuração ao instalar uma nova versão do seu software?

Ainda não vi boas soluções que funcionem bem em todos os casos, no entanto, vi alguns soluções parciais(Isso pode ser combinado em diferentes combinações, conforme necessário), que reduz muito o problema.

  • Em primeiro lugar, reduza o número de itens de configuração que você possui em seu arquivo de configuração principal.

    Se você não precisa permitir que seus clientes alterem seus mapeamentos, use Fluent NHibernate (ou outro) para mover a configuração para o código.

    Da mesma forma para configuração de injeção de dependência.

  • Divida o arquivo de configuração quando possível, por ex.use um arquivo separado para configurar quais logs do Log4Net.

  • Não repita itens entre muitos arquivos de configuração, por exemplo.se você tiver 4 aplicativos da web instalados na mesma máquina, tenha um arquivo de configuração geral para o qual o arquivo web.config de cada aplicativo aponta.

    (Use um caminho relativo por padrão, por isso é raro ter que alterar o arquivo web.config)

  • Processe o arquivo de configuração de desenvolvimento para obter o arquivo de configuração de envio.

    Isso pode ser feito com valores padrão nos comentários XML que são definidos no arquivo de configuração quando uma compilação é concluída.Ou ter seções que são excluídas como parte do processo de criação do instalador.

  • Em vez de ter apenas uma string de conexão de banco de dados, tenha uma para cada desenvolvedor.

    Por exemplo, primeiro procure por “database_ianr” (onde ianr é meu nome de usuário ou nome da máquina) no arquivo de configuração em tempo de execução, se não for encontrado, procure por “database”

    Tenha um 2º nível "por ex.-oracle ou -sqlserver" tornam mais rápido para os desenvolvedores acessarem ambos os sistemas de banco de dados.

    É claro que isso também pode ser feito para qualquer outro valor de configuração.

    Então, todos os valores que terminam em “_userName” podem ser eliminados antes de enviar o arquivo de configuração.

No entanto, no final, o que você é um "proprietário do arquivo de configuração" que leva a responsabilidade de gerenciar o (s) arquivo (s) de configuração (s) acima ou não.Ele/ela também deve fazer uma diferença no arquivo de configuração do cliente antes de cada remessa.

Você não pode eliminar a necessidade de uma pessoa atenciosa com esse problema.

Não creio que exista uma solução única que funcione para todos os casos, pois pode depender da sensibilidade dos dados nos arquivos de configuração, da linguagem de programação que você está usando e de muitos outros fatores.Mas acho importante manter os arquivos de configuração de todos os ambientes sob controle de origem, para que você possa sempre saber quando foi alterado e por quem e, mais importante, poder recuperá-lo se algo der errado.E eles irão.

Então aqui está como eu faço isso.Geralmente, isso é para projetos nodejs, mas acho que funciona para outras estruturas e linguagens também.

O que eu faço é criar um configs diretório na raiz do projeto e, nesse diretório, mantenha vários arquivos para todos os ambientes (e às vezes arquivos separados para o ambiente de cada desenvolvedor também), que são todos rastreados no controle de origem.E há o arquivo real que o código usa chamado config na raiz do projeto.Este é o único arquivo que não é rastreado.Então é assim

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

Quando alguém verifica o projeto, ele copia o arquivo de configuração que deseja usar no untracked config arquivo e ele é livre para editá-lo como desejar, mas também é responsável por copiar essas alterações antes de enviar para os outros arquivos do ambiente, conforme necessário.

E nos servidores, o arquivo não rastreado pode ser simplesmente uma cópia (ou referência) do arquivo rastreado correspondente a esse ambiente.Em JS você pode simplesmente ter 1 linha para exigir esse arquivo.

Este fluxo pode ser um pouco complicado no início, mas tem grandes vantagens:1.Você nunca precisa se preocupar com um arquivo de configuração ser excluído ou modificado no servidor sem ter um backup 2.O mesmo se um desenvolvedor tiver alguma configuração personalizada em sua máquina e sua máquina parar de trabalhar por qualquer motivo 3.Antes de qualquer implantação, você pode diferenciar os arquivos de configuração para development e staging por exemplo e veja se há algo faltando ou quebrado.

Apenas mantemos o arquivo de configuração de produção em check-in.É responsabilidade do desenvolvedor alterar o arquivo ao retirá-lo do código-fonte seguro para teste ou desenvolvimento.Isso nos queimou no passado, então eu não sugeriria isso.

Eu enfrentei o mesmo problema e encontrei uma solução para ele.Primeiro adicionei todos os arquivos ao repositório central (também os do desenvolvedor).

Portanto, se um desenvolvedor buscar os arquivos do repositório, a configuração do desenvolvedor também estará lá.Ao fazer alterações neste arquivo, o Git não deve estar ciente dessas alterações.Dessa forma, as alterações não podem ser enviadas/confirmadas para o repositório, mas permanecem localmente.

Eu resolvi isso usando o comando git: update-index --assume-unchanged.Fiz um arquivo bat que é executado no pré-build dos projetos que contém um arquivo cujas alterações devem ser ignoradas pelo Git.Aqui está o código que coloquei no arquivo 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

Na minha pré-construção eu faria uma chamada para o arquivo bat, por exemplo:

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

Encontrei no SO um arquivo bat que copia o arquivo de configuração correto para web.config/app.config.Eu também chamo esse arquivo bat na pré-construção.O código para este arquivo bat é:

@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.

Na minha pré-construção eu faria uma chamada para o arquivo bat, por exemplo:

call "$(ProjectDir)\..\..\copyifnewer.bat" "$(ProjectDir)web.config.$(ConfigurationName)" "$(ProjectDir)web.config
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top