Как убедиться, что мы публикуем production на prod-сервере и testируем на тестовом сервере

StackOverflow https://stackoverflow.com/questions/651668

  •  19-08-2019
  •  | 
  •  

Вопрос

У меня есть запись в моем файле Web.Config, которая указывает, в какой среде я нахожусь, для строк подключения и нежелательной почты:

<add key="AppEnv" value ="2" /> <!--(0 = Dev, 1 = test, 2 = prod)--> 

Я ищу способ предупредить разработчика во время публикации, чтобы убедиться, что они проверили этот ключ / значение, чтобы они не публиковали "тест" на сервере "prod" и наоборот.

Спасибо

Это было полезно?

Решение

Я придумал свое собственное (вероятно, нетрадиционное) решение этой проблемы.Мы разрабатываем множество различных веб-проектов для множества разных клиентов и перенесли их все на этот метод из-за всех проблем, возникших у нас с несколькими файлами web.config, или из-за необходимости внесения изменений перед публикацией.

По сути, мы позволяем нашему приложению сообщать нам, в какой среде оно работает, на основе входящего URL.Мы инициализируем это при первом запросе и сохраняем в памяти на весь срок службы приложения.Таким образом, мы можем сохранить каждое из конфигурационных значений, специфичных для нашей среды, в одном и том же конфигурационном файле и просто квалифицировать их с помощью Development, Staging, Production и т.д.И любые настройки, которые не отличаются в разных средах, не нуждаются в уточнении.

Сначала пример web.config:

<appSettings>
    <add key="DevelopmentHost" value="dev.trackmyhours.com" />
    <add key="StagingHost" value="staging.trackmyhours.com" />
    <add key="ProductionHost" value="www.trackmyhours.com" />
  </appSettings>

  <connectionStrings>
    <clear />
    <add name="DevelopmentConnectionString" connectionString="your dev conn string" providerName="System.Data.SqlClient" />
    <add name="StagingConnectionString" connectionString="your staging conn string (mine is typically same as staging)" providerName="System.Data.SqlClient" />
    <add name="ProductionConnectionString" connectionString="your production conn string" providerName="System.Data.SqlClient" />
  </connectionStrings>

Далее у нас есть класс "App", который предоставляет нам доступ к нашему классу "Site", но вы можете создавать свои классы так, как считаете нужным.

Public Class App

    Private Shared _Site As New Site
    Public Shared ReadOnly Property Site() As Site
        Get
            Return _Site
        End Get
    End Property

End Class

Imports System.Configuration
Imports System.Web

Public Class Site

    Public Enum EnvironmentType
        Development
        Staging
        Production
    End Enum

    Friend Sub New()

        If HttpContext.Current IsNot Nothing Then

            Dim URL = HttpContext.Current.Request.Url.DnsSafeHost

            Select Case URL
                Case ConfigurationManager.AppSettings("DevelopmentHost"), "localhost"
                    _Environment = EnvironmentType.Development
                Case ConfigurationManager.AppSettings("StagingHost")
                    _Environment = EnvironmentType.Staging
                Case ConfigurationManager.AppSettings("ProductionHost")
                    _Environment = EnvironmentType.Production
            End Select

        Else
            'probably getting called from a winforms/console app, or unit tests
            _Environment = EnvironmentType.Staging

        End If

        _ConnectionString = ConfigurationManager.ConnectionStrings(_Environment.ToString & "ConnectionString").ConnectionString

    End Sub


    Private _Environment As EnvironmentType
    Public Property Environment() As EnvironmentType
        Get
            Return _Environment
        End Get
        Set(ByVal value As EnvironmentType)
            _Environment = value

            _ConnectionString = ConfigurationManager.ConnectionStrings(_Environment.ToString & "ConnectionString").ConnectionString

        End Set
    End Property

    Private _ConnectionString As String
    Public ReadOnly Property ConnectionString() As String
        Get
            Return _ConnectionString
        End Get
    End Property

End Class

Мы помещаем наши классы в нашу библиотеку классов Biz Object.Мы просто решили, что нет необходимости определять среду при каждом отдельном запросе, поскольку она действительно не может измениться в течение срока службы приложения.Кроме того, это позволяет нам ссылаться на App.Site.Окружение из ЛЮБОГО места в коде библиотеки или из исходного кода.Это также полезно, если вам нужно добавить в свой код некоторую условную логику - например, не отправлять электронные письма реальным людям при запуске в dev / staging.

И последнее - для наших Linq2SQL или EF Data / ObjectContexts мы не храним строку подключения в файле, а вместо этого перегружаем конструктор, чтобы мы могли предоставить нашу правильную строку подключения к среде следующим образом:

Partial Class SampleDataContext
    Sub New()
        MyBase.New(App.Site.ConnectionString)
    End Sub
End Class

Другие советы

Вот решение:сохраните этот файл как "Web.Config.in" под контролем источника.

На каждом сервере (dev, test, staging, production) скопируйте Web.Config.in Для Web.Config, и отредактируйте AppEnv тщательно оценивайте.

При каждом последующем перемещении из одной среды в следующую исключайте Web.Config Файлы.То есть, не перезаписывайте этот конкретный файл.Напишите сценарии развертывания, которые запускают rsync --exclude WebConfig например.

В верхней части страницы жирными красными буквами указано, в каком режиме находится сайт, если он не находится в рабочем режиме.

У меня также есть страница диагностики, на которой указано, на каком сервере запущен и к какой базе данных он подключен.

Вы также могли бы поместить таблицу подстановки в каждую базу данных, чтобы убедиться, что у вас к ней подключен правильный флаг.(в тестовой базе данных отметьте это как 1 и проверьте в Application_Start, совпадают ли значения)

Всякий раз, когда возникает процесс, который всегда требует более одного шага, я знаю, что испорчу его по крайней мере в половине случаев.По этой причине я люблю MSBuild.

Существует довольно много полезных задач, которые поставляются в комплекте с MSBuild, таких как Задача AspNetCompiler, которое, по-видимому, представляет собой одноэтапное действие компиляции / публикации.

Существует также несколько проектов, которые объединяют большое количество "пользовательских" задач MSBuild для различных целей.В Проект Задач сообщества MSBuild имеет задачу XmlMassUpdate, которая полезна для внесения нескольких изменений в файл в формате xml.Другими словами, идеально подходит для обновления файлов web.config.

Я нашел пример использования задачи XmlMassUpdate совместно с проектом веб-развертывания здесь.

Вечный вопрос, который постоянно всплывает!Я думаю, почти любой серьезный разработчик ASP.NET в некотором роде столкнулся с этим.

Для версии ASP.NET 4.0 уже готовится некоторая помощь - улучшенные параметры веб-развертывания будут предлагать функцию под названием "преобразования web.config".

Посмотри на это Видео с 9 канала по теме - пока не нашел ни одной приличной письменной ссылки...

Марк

Я беру любые ключи, которые будут отличаться в тестировании и на производстве, и помещаю их в совершенно новый файл .config .Я помещаю настройки теста в test, а производственные настройки - в production и никогда не копирую этот файл из test в production.Затем в вашем обычном web.config вы можете указать этот новый файл .config следующим образом:

<appSettings file="ExternalWeb.config>
    .... common keys go here
</appSettings>

на тестовом сервере "external.config" будет содержать значения, специфичные для этого сервера, а в рабочей среде он будет иметь значения prod.Это позволяет вам скопировать весь ваш web.config между двумя серверами, даже не изменяя файл вручную.

Я думаю, что это плохая практика хранить строки подключения в web.config, я вместо этого создаю отдельный конфигурационный файл за пределами моих веб-сайтов в общеизвестном месте, например

C:\xxxx\config.xml

Затем я сохраняю там все настройки, зависящие от компьютера.Таким образом, на моем живом сервере у меня есть свои текущие настройки, на тестовом сервере - строки подключения к тестовой базе данных, а на моей машине разработчика я получил свои локальные настройки.Затем эти настройки также могут быть повторно запущены на всех веб-сайтах и .net-приложениях на этом сервере.Только одно место для обновления при изменении базы данных.

Идеально!

Установите для вашего Web.Config значение "Только для чтения", поэтому он не будет перезаписан при публикации на этих серверах.

Компромисс заключается в том, что вам придется вручную поддерживать свои web.config на каждом сервере, и ваша публикация будет считаться неудачной, поскольку она не смогла перезаписать web.config на удаленном сервере;но ИМХО это предпочтительнее, чем изменять конфигурацию каждый раз, когда вы выполняете загрузку

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top