Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ADN Columbus 2013 - Continuous Deployment to Bu...

Improving
August 19, 2013

ADN Columbus 2013 - Continuous Deployment to Build Trust

Improving

August 19, 2013
Tweet

More Decks by Improving

Other Decks in Education

Transcript

  1. Chris Weldon u  Principal Consultant u  Microsoft MVP u  Slings

    Code in C# and PHP u  Systems Administrator devops u  [email protected] u  @neraath
  2. As a conference presenter, I would like a web site

    with upcoming conferences, so I can stay in-the-know on the conference circuit.
  3. As a conference presenter, I would like to see a

    list of upcoming conferences, so that I know what to submit presentations for.
  4. As a conference organizer, I would like conferences I create

    to persist beyond my session so that other users can see upcoming conferences.
  5.        public  class  Conference        

     {                  public  int  Id  {  get;  set;  }                  [Required]                  public  string  Name  {  get;  set;  }          }
  6.        public  partial  class  Initial  :  DbMigration  

           {                  public  override  void  Up()                  {                          CreateTable(                                  "dbo.Conferences",                                  c  =>  new                                          {                                                  Id  =  c.Int(nullable:  false,  identity:  true),                                                  Name  =  c.String(nullable:  false),                                          })                                  .PrimaryKey(t  =>  t.Id);                                            }                                    public  override  void  Down()                  {                          DropTable("dbo.Conferences");                  }          }
  7.        public  class  Conference        

     {                  public  int  Id  {  get;  set;  }                  [Required]                  public  string  Name  {  get;  set;  }                  [Required]                  public  string  Description  {  get;  set;  }                  public  DateTime  StartTime  {  get;  set;  }                  public  DateTime  EndTime  {  get;  set;  }          }
  8.        public  partial  class  DescriptionAndDates  :  DbMigration  

           {                  public  override  void  Up()                  {                          AddColumn("dbo.Conferences",  "Description",  c  =>  c.String(nullable:  false));                          AddColumn("dbo.Conferences",  "StartTime",  c  =>  c.DateTime(nullable:  false));                          AddColumn("dbo.Conferences",  "EndTime",  c  =>  c.DateTime(nullable:  false));                  }                                    public  override  void  Down()                  {                          DropColumn("dbo.Conferences",  "EndTime");                          DropColumn("dbo.Conferences",  "StartTime");                          DropColumn("dbo.Conferences",  "Description");                  }          }
  9. As a systems administrator, I would like enable caching of

    conferences from the database so that we can minimize the impact of querying the database.
  10. Scenario: Multiple web applications u  CritterMatch Core Business Libraries (CMCBL)

    u  CritterMatch.com depends on: u  log4net v1.0.6 u  Entity Framework v4 u  ASP.Net Web API v1.0.0 u  CMCBL v1.0.0 u  CritterMatch Business Services depends on: u  log4net v1.2.1 u  Entity Framework v5 u  ASP.Net Web API v1.2.2 u  CMCBL v1.1.0
  11. Scenario: Multiple web applications u  CritterMatch.com u  Developer Workstations u 

    Integration/QA u  Staging u  Production u  CritterMatch Business Services u  Developer Workstations u  Integration/QA u  Production – Client A u  Production – Client B
  12. Configuration Management u  Configurations likely to change: u  Database Connection

    Strings u  Web Service Connection Endpoints u  Authorized Users? u  Requirements Management u  Different views or behaviors u  Dependency Injection? u  Often times a configuration change, too.
  13.    <connectionStrings>          <add  name="DefaultConnection"  providerName="System.Data.SqlClient"  connectionString="Data

      Source=(LocalDb)\v11.0;Initial  Catalog=aspnet-­‐convene-­‐20130513144609;Integrated   Security=SSPI;"  />      </connectionStrings>      <appSettings>          <add  key="webpages:Version"  value="2.0.0.0"  />          <add  key="webpages:Enabled"  value="false"  />          <add  key="PreserveLoginUrl"  value="true"  />          <add  key="ClientValidationEnabled"  value="true"  />          <add  key="UnobtrusiveJavaScriptEnabled"  value="true"  />      </appSettings> web.config
  14. web.config Transforms <configuration  xmlns:xdt="http://schemas.microsoft.com/XML-­‐Document-­‐Transform">          <connectionStrings>  

               <add  name="DefaultConnection"                    connectionString="Data  Source=DB1.improving.com;Initial  Catalog=convene;Integrated   Security=True"                    xdt:Transform="SetAttributes"  xdt:Locator="Match(name)"/>          </connectionStrings>      <system.web>          <compilation  xdt:Transform="RemoveAttributes(debug)"  />              <customErrors  defaultRedirect="GenericError.htm"                  mode="RemoteOnly"  xdt:Transform="Replace">                  <error  statusCode="500"  redirect="InternalError.htm"/>              </customErrors>      </system.web>   </configuration>
  15. Making Logging Useful to Ops & Engineering u  Ops needs

    to know: u  Network connection problems u  Load problems u  Service/dependency outages u  Consider surfacing events to event log for ops, leaving log files to devs u  Engineering needs to know: u  Everything that ops needs to know u  Performance
  16. Debug is never for production u  Not constantly, that is.

    u  If you are trying to debug the production database query, you’re doing it wrong. u  If you are trying to figure out the object model being sent to the view, you’re doing it wrong. u  If you are trying to debug the workflow of your application, you’re doing it wrong. u  The highest level of constant production logging should be INFO. u  Info serves for interactions between customers and your site. u  Info surfaces information customers have requested, but never the interactions of your code.
  17. Exception Management u  Don’t always surface exceptions to your Event

    Log if Ops is monitoring u  Boy Who Cried Wolf u  Be meticulous about which exceptions are surfaced out of your application u  Exceptions are expensive
  18. devops u  The collaboration, communication, and integration between developers and

    operations to reduce the friction of getting software releases into production.
  19. Gherkin Feature:  CreateConference   As  a  conference  organizer   I

     would  like  to  create  a  conference   So  that  I  can  manage  the  details  of  the  conference.       Scenario:  Attempting  to  create  a  conference  without  times  throws  a  validation  error   Given  I  submit  the  Name  of  the  conference  as  AgileDotNet   When  I  create  the  conference   Then  I  should  get  a  validation  error     Scenario:  Creating  a  conference  with  name  and  times  creates  the  conference   Given  I  submit  the  Name  of  the  conference  as  AgileDotNet   And  I  submit  the  Description  of  the  conference  as            "Great  content  blending  the  world  of  Agile  with  DotNet  development"   And  I  submit  the  StartTime  of  the  conference  as  2013-­‐05-­‐17  08:00:00   And  I  submit  the  EndTime  of  the  conference  as  2013-­‐05-­‐17  18:00:00   When  I  create  the  conference   Then  I  should  get  the  status  code  Created  
  20. [Given("I  submit  the  (.*)  of  the  conference  as  (.*)")]  

    public  void  GivenIHaveSubmittedConferenceInformation(string  field,  string  value)   {          var  conferenceType  =  typeof  (Conference);          var  fieldInfo  =  conferenceType.GetProperty(field);          if  (fieldInfo  ==  null)  throw  new  Exception("No  field  by  name  "  +  field  +  "  found.");            if  (fieldInfo.PropertyType  ==  typeof(DateTime))                  fieldInfo.SetValue(ConferenceToSubmit,  DateTime.Parse(value));          else                  fieldInfo.SetValue(ConferenceToSubmit,  value);   }
  21. [When("I  create  the  conference")]   public  void  WhenICreateTheConference()   {

             try          {                  Result  =  Controller.Post(ConferenceToSubmit);          }          catch  (Exception  e)          {                  Result  =  e;          }   }
  22. [Then("I  should  get  the  status  code  (.*)")]   public  void

     IShouldGetAStatusCode(string  statusCodeName)   {          Assert.IsInstanceOfType(typeof(HttpResponseMessage),  Result,  "Expected  an   HttpResponseMessage.");          var  message  =  (HttpResponseMessage)Result;          HttpStatusCode  statusCode;          Enum.TryParse<HttpStatusCode>(statusCodeName,  true,  out  statusCode);          Assert.AreEqual(statusCode,  message.StatusCode);   }
  23. Q&A