TheCB4

App DevOps with Make Part 2


If you are not familiar with GNU Make, it is a tool to help automate development processes. I have been using it to help with my "one-man-band" development process.

Part 1 is here

Why use Make?


I decided to use make instead of tools like FastLine because I didn't want to introduce another language outside of shell scripts and Swift into my process. I also wanted to learn and stay close to how each step in my development process was done.

What am I using Make for?


I have a fascination with the process of development. How do you simplify the effort and eliminate the noise and focus on the app itself. I have a fairly straight forward process for devops that I've codified into steps in Make.


  • Manage branches - I use them for features
  • Review - Lint and Format the code
  • Secrets - hide and unhide secrets used within the devops pipeline
  • Increment Build
  • Build & Test the app
  • Commit the source in git
  • Merge Request in gitlab
  • Archive, Package, and Post the app to TestFlight
  • Generate my website for my app

    Review

    I plan on doing more around code reviews in general but at the very least I have a step in my devops process where I lint and format my code. If you not familiar with code linting. Linting is the automated checking of your source code for programming and style errors. In most cases the development tools that you use check for programming errors. So in most cases Linters that are used today check style/convention and help with what are called "code smells". I use swift-format for this. The most popular is SwiftLint. Choose whichever works for you, but definitely use one. I use swift-format because I can Lint and then format my code with the same tool.


    My linting rules are as follows:


    
     {
      "fileScopedDeclarationPrivacy" : {
        "accessLevel" : "private"
      },
      "indentation" : {
        "spaces" : 2
      },
      "indentConditionalCompilationBlocks" : true,
      "indentSwitchCaseLabels" : true,
      "lineBreakAroundMultilineExpressionChainComponents" : true,
      "lineBreakBeforeControlFlowKeywords" : false,
      "lineBreakBeforeEachArgument" : false,
      "lineBreakBeforeEachGenericRequirement" : false,
      "lineLength" : 100,
      "maximumBlankLines" : 1,
      "prioritizeKeepingFunctionOutputTogether" : false,
      "respectsExistingLineBreaks" : true,
      "rules" : {
        "AllPublicDeclarationsHaveDocumentation" : true,
        "AlwaysUseLowerCamelCase" : true,
        "AmbiguousTrailingClosureOverload" : true,
        "BeginDocumentationCommentWithOneLineSummary" : true,
        "DoNotUseSemicolons" : true,
        "DontRepeatTypeInStaticProperties" : true,
        "FileScopedDeclarationPrivacy" : true,
        "FullyIndirectEnum" : true,
        "GroupNumericLiterals" : true,
        "IdentifiersMustBeASCII" : true,
        "NeverForceUnwrap" : true,
        "NeverUseForceTry" : true,
        "NeverUseImplicitlyUnwrappedOptionals" : false,
        "NoAccessLevelOnExtensionDeclaration" : true,
        "NoBlockComments" : true,
        "NoCasesWithOnlyFallthrough" : true,
        "NoEmptyTrailingClosureParentheses" : true,
        "NoLabelsInCasePatterns" : true,
        "NoLeadingUnderscores" : false,
        "NoParensAroundConditions" : true,
        "NoVoidReturnOnFunctionSignature" : true,
        "OneCasePerLine" : true,
        "OneVariableDeclarationPerLine" : true,
        "OnlyOneTrailingClosureArgument" : true,
        "OrderedImports" : true,
        "ReturnVoidInsteadOfEmptyTuple" : true,
        "UseLetInEveryBoundCaseVariable" : true,
        "UseShorthandTypeNames" : true,
        "UseSingleLinePropertyGetter" : true,
        "UseSynthesizedInitializer" : true,
        "UseTripleSlashForDocumentationComments" : true,
        "ValidateDocumentationComments" : true
      },
      "tabWidth" : 2,
      "version" : 1
    }
    

    The Makefile commands are:

    feature-review: format lint
    
    format:
    			swift format --mode format -i --configuration .swift-format.json -r \
    			Sources/Shared \
    			Sources/iOS \
    			Sources/macOS \
    			Tests/Support \
    			Tests/Tests\ iOS \
    			Tests/Tests\ macOS \
    			Tests/Tests\ iOS\ Unit \
    			Tests/Tests\ macOS\ Unit \
    			Tests/Shared
    		@echo Formatting complete
    
    lint:
    		swift format --mode lint --configuration .swift-format.json -r \
    			Sources/Shared \
    			Sources/iOS \
    			Sources/macOS \
    			Tests/Support \
    			Tests/Tests\ iOS \
    			Tests/Tests\ macOS \
    			Tests/Tests\ iOS\ Unit \
    			Tests/Tests\ macOS\ Unit \
    			Tests/Shared
    		@echo Linting complete
    

    I also have a local version of this that manages my secrets

    review-local: secrets format lint
    
    secrets:
    	git secret hide
    

    I format before I lint so I'm only dealing with real issues. Swift-Format doesn't include some of the additional bells and whistles like SwiftLint but SwiftLint doesn't autocorrect everything.


    I use git-secret to manage my secrets files. I use two different sets of calls for local work vs. Continuous Integration or CI work. Running 'git secret hide' encrypts any key files or environment variables so I don't store them in plain text in my repository.

    Those are my review steps in my DevOps process. What are your review steps?

    Tagged with: