Skip to content

Contributing

github-actions edited this page Feb 9, 2023 · 25 revisions

Contents


Looking to contribute to this project, whether that be Bicep code, examples, documentation or GitHub automation, you are in the right place. Please review the rest of this wiki page for important information to help you to start contributing to the project effectively.

Recommended Learning

Before you start contributing to the ALZ Bicep code, it is highly recommended that you complete the following Microsoft Learn paths, modules & courses:

Bicep

Git

Tooling

Required Tooling

To contribute to this project the following tooling is required:

Bicep Logo

Recommended Tooling

The following tooling/extensions are recommended to assist you developing for the project:

Bicep Formatting Guidelines

The below guidelines should be adhered to whilst contributing to this projects Bicep code.

Bicep Best Practices

Throughout the development of Bicep code you should follow the Bicep Best Practices.

It is suggested to keep this page open whilst developing for easy reference

Bicep Code Styling

  • Strict camelCasing must be used for all elements:
    • Symbolic names for:
      • Parameters
      • Variables
      • Resource
      • Modules
      • Outputs
  • All par and out values in Bicep templates should include full product name instead of camelCased abbreviation, for example: parExpressRouteGwName instead of parErGwName
  • Services with "Azure" in the name are abbreviated "Az", for example: parAzBastionName instead of parAzureBastionName
  • Use parameter decorators to ensure integrity of user inputs are complete and therefore enable successful deployment
    • Only use the @secure() parameter decorator for inputs. Never for outputs as this is not stored securely and will be stored/shown as plain-text!
  • A description is required on parameters to provide an explanation into their function. As metadata is used in Bicep modules, sys.description('description here') is the chosen formatting. More information can be found in the Azure Bicep documentation
  • Comments should be provided where additional information/description of what is happening is required, except when a decorator like @sys.description('Example description') is providing adequate coverage
    • Single-line // <comment here> and multi-line /* <comment here> */ comments are both welcomed
    • Provide contextual public Microsoft documentation recommendation references/URLs in comments to help user understanding of code implementation
  • All expressions, used in conditionals and loops, should be stored in a variable to simplify code readability
  • Specify default values for all parameters where possible - this improves deployment success
    • The default value should be called out in the description of the parameter for ease of visibility
    • Default values should also be documented in the appropriate location
  • Tab indents should be set to 2 for all Bicep files
  • Double line-breaks should exist between each element type section
  • When intended for scopes above resource group deployment, targetScope should be indicated at the beginning of the file

Bicep Elements Naming Standards

Element Type Naming Prefix Example
Parameters par parLocation, parManagementGroupsNamePrefix
Variables var varConditionExpression, varIntermediateRootManagementGroupName
Resources res resIntermediateRootManagementGroup, resResourceGroupLogAnalytics
Modules mod modManagementGroups, modLogAnalytics
Outputs out outIntermediateRootManagementGroupID, outLogAnalyticsWorkspaceID

Bicep Common Parameters Naming Standards

The below guidelines should be adhered to whilst contributing to this projects Bicep code.

  • parLocation
    • Shall be used for all module parameters specifying the Azure region to which a resource or module will be deployed.
    • The only exception to this is when two inter-related services do not have region parity and need to be deployed to different regions. (i.e. Log Analytics and Automation Accounts in China. See logging module for an example)

Bicep File Structure

For all Bicep files created as part of this project they will follow the structure pattern of being grouped by element type, this is shown in the image below:

Bicep File Structure By Element Type Image

Parameters, Variables, Resources, Modules & Outputs are all types of elements.

Bicep File Structure Example

Below is an example of Bicep file complying with the structure and styling guidelines specified above:

// SCOPE
targetScope = 'subscription' //Deploying at Subscription scope to allow resource groups to be created and resources in one deployment


// PARAMETERS
@sys.description('Example description for parameter. - DEFAULT VALUE: "TEST"')
param parExampleResourceGroupNamePrefix string = 'TEST'


// VARIABLES
var varExampleResourceGroupName = 'rsg-${parExampleResourceGroupNamePrefix}' // Create name for the example resource group


// RESOURCE DEPLOYMENTS
resource resExampleResourceGroup 'Microsoft.Resources/resourceGroups@2021-04-01' = {
  name: varExampleResourceGroupName
  location: 'uksouth' // Hardcoded as an example of commenting inside a resource
}

/*
No modules being deployed in this example
*/


// OUTPUTS
output outResourceGroupExampleID string = resExampleResourceGroup.id

Constructing a Bicep Module

To author Bicep modules that are in-line with the requirements for this project, the following must be true:

  • Follows the Bicep Formatting Guidelines as detailed above
  • A new folder per module in the following directory: infra-as-code/bicep/modules/...
    • Folder Name will be created with camel case: infra-as-code/bicep/modules/moduleName
  • Each new module folder must contain:
    • A media folder that will contain images used in the README.md
    • A README.md for each module in the root of its own folder, as above, detailing the module, what it deploys and any other useful information for consumers.
      • The README.md must also contain a Bicep visualizer image of the complete module
    • Parameter detail files are automatically generated in the generateddocs folder of each module after contributing to the repository. A link in the README.md file must be created.
    • When contributing a module to the repository, anticipate creation of the markdown for the parameters. To link to the parameters after contribution, use the following structure in the parameters section of the readme:

- [Link to Azure Commercial Cloud/Azure China Cloud](generateddocs/<NAME-OF-BICEP-MODULE-FILE.bicep.md)

Parameter Markdown Generation Workflow

On your Pull Request (PR), the following steps will happen:

  • PR is created.
  • GitHub Action Workflow initialises.
    • The PR Branch is checked out.
    • A Bicep Build is run on each of the modules.
    • PSDocs For Azure generates a markdown file against each of the built JSON files in the module folders.
    • A generateddocs folder is created in each of the modules.
    • The markdown files are stored in this folder for each of the modules.
    • Removal of the JSON files from the Bicep Build task is done.
    • A git status and push is then done to the same PR for the created/updated generated documentation to complete the workflow.

bicepconfig.json

  • A bicepconfig.json for each module in the root of its own folder.

    • Bicep Linting Documentation

    • The bicepconfig.json file should contain the following:

            {
              "analyzers": {
                "core": {
                  "enabled": true,
                  "verbose": true,
                  "rules": {
                    "adminusername-should-not-be-literal": {
                      "level": "error"
                    },
                    "no-hardcoded-env-urls": {
                      "level": "error"
                    },
                    "no-unnecessary-dependson": {
                      "level": "error"
                    },
                    "no-unused-params": {
                      "level": "error"
                    },
                    "no-unused-vars": {
                      "level": "error"
                    },
                    "outputs-should-not-contain-secrets": {
                      "level": "error"
                    },
                    "prefer-interpolation": {
                      "level": "error"
                    },
                    "secure-parameter-default": {
                      "level": "error"
                    },
                    "simplify-interpolation": {
                      "level": "error"
                    },
                    "protect-commandtoexecute-secrets": {
                      "level": "error"
                    },
                    "use-stable-vm-image": {
                      "level": "error"
                    },
                    "explicit-values-for-loc-params": {
                      "level": "error"
                    },
                    "no-hardcoded-location": {
                      "level": "error"
                    },
                    "no-loc-expr-outside-params": {
                      "level": "error"
                    },
                    "max-outputs": {
                      "level": "error"
                    },
                    "max-params": {
                      "level": "error"
                    },
                    "max-resources": {
                      "level": "error"
                    },
                    "max-variables": {
                      "level": "error"
                    },
                    "artifacts-parameters":{
                      "level": "error"
                    },
                    "no-unused-existing-resources":{
                      "level": "error"
                    },
                    "prefer-unquoted-property-names":{
                      "level": "error"
                    },
                    "secure-params-in-nested-deploy":{
                      "level": "error"
                    },
                    "secure-secrets-in-params":{
                      "level": "error"
                    },
                    "use-recent-api-versions":{
                      "level": "error"
                    },
                    "use-resource-id-functions":{
                      "level": "error"
                    },
                    "use-stable-resource-identifiers":{
                      "level": "error"
                    }
                  }
                }
              }
            }
  • The Bicep module file

  • A parameters folder that will contain the parameters files for the module

  • Parameters ...all.json and ...min.json files based on file naming convention below

  • Parameter files should be named according to the convention: <module>.<parameterSet>.parameters.<min|all>.json

    • <module> denotes the current module (and scope when necessary), for example: roleAssignmentManagementGroup
    • <parameterSet> denotes a set of parameters with similar characteristics, for example: securityGroup
    • parameters constant to denote the file as a parameters file
    • <min|all>.json denotes whether a parameter file contains all possible parameters or only minimum necessary for deployment

Resource API Versions

Each resource must use the latest available, working, API version. If the latest API version cannot be used for any reason, a comment must be placed above the resource in the module file stating why and also called out as part of the PR.

The Bicep linter rule use-recent-api-versions will now also check for this 👍