Repository: kubernetes-sigs/cluster-api-provider-azure (go)

Issue:
Replacing Windows with Windows + WSL2 for clarification
/kind documentation

Currently the docs mention setting up of the project in Windows OS, but for better results it is suggested the project is set up in a nix environment.

**Describe the solution you'd like**
Modifying the docs and mentioning the setting up of the project in Windows + WSL2 instead Windows. This would provide clarification that the files should be checked out to wsl file system for obtaining better results.


**Anything else you would like to add:**
[Miscellaneous information that will assist in solving the issue.]


**Environment:**

- cluster-api-provider-azure version: 
- Kubernetes version: (use `kubectl version`): 
- OS (e.g. from `/etc/os-release`): 


Pull request:
Replaced Windows with Windows + WSL2
 <!-- If this is your first PR, welcome! Please make sure you read the [contributing guidelines](../CONTRIBUTING.md). -->

 <!-- Please label this pull request according to what type of issue you are addressing (see ../CONTRIBUTING.md) -->
**What type of PR is this?**

<!--
Add one of the following kinds:
/kind documentation
-->

**What this PR does / why we need it**:

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #1608 

**Special notes for your reviewer**:

_Please confirm that if this PR changes any image versions, then that's the sole change this PR makes._

**TODOs**:
<!-- Put an "X" character inside the brackets of each completed task. Some may be optional depending on the PR. -->

- [x] squashed commits
- [ ] includes documentation
- [ ] adds unit tests

**Release note**:
<!--  Write your release note:
1. Enter your extended release note in the below block. If the PR requires additional action from users switching to the new release, include the string "action required".
2. If no release note is required, just write "NONE".
-->
```release-note
NONE
```


Patch:
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 73b6880b3..8bef598ce 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -6,6 +6,8 @@ about: Tell us about a problem you are experiencing.
 
 /kind bug
 
+[Before submitting an issue, have you checked the [Troubleshooting Guide](https://capz.sigs.k8s.io/topics/troubleshooting.html)?]
+
 **What steps did you take and what happened:**
 [A clear and concise description of what the bug is.]
 
diff --git a/.github/workflows/cover.yaml b/.github/workflows/cover.yaml
index 7ac446d8a..5b5a441ab 100644
--- a/.github/workflows/cover.yaml
+++ b/.github/workflows/cover.yaml
@@ -7,8 +7,10 @@ jobs:
   coverage:
     runs-on: ubuntu-latest
     steps:
-    - uses: actions/checkout@master
-    - run: "bash hack/install-go.sh"
+    - uses: actions/checkout@v2
+    - uses: actions/setup-go@v2
+      with:
+        go-version: '^1.17'
     - run: "PATH=/usr/local/go/bin:$PATH make test-cover"
     - uses: codecov/codecov-action@v1
       with:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
new file mode 100644
index 000000000..0c12e659c
--- /dev/null
+++ b/.github/workflows/release.yaml
@@ -0,0 +1,37 @@
+on:
+  push:
+    # Sequence of patterns matched against refs/tags
+    tags:
+    - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
+
+name: release
+
+jobs:
+  build:
+    name: tag release
+    runs-on: ubuntu-latest
+    steps:
+      - name: Set env
+        run:  echo "RELEASE_TAG=${GITHUB_REF:10}" >> $GITHUB_ENV
+      - name: checkout code
+        uses: actions/checkout@v2
+        with:
+          fetch-depth: 0
+      - name: Install go
+        uses: actions/setup-go@v2
+        with:
+          go-version: '^1.17'
+      - name: generate release artifacts
+        run: |
+          make release
+      - name: generate release notes
+        run: |
+          make release-notes
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+      - name: Release
+        uses: softprops/action-gh-release@v1
+        with:
+          draft: true
+          files: out/*
+          body_path: release-notes-${{ env.RELEASE_TAG }}.md
diff --git a/Makefile b/Makefile
index 77e6d3b60..fdcafc86d 100644
--- a/Makefile
+++ b/Makefile
@@ -405,8 +405,11 @@ set-manifest-pull-policy:
 ## Release
 ## --------------------------------------
 
-RELEASE_TAG := $(shell git describe --abbrev=0 2>/dev/null)
-RELEASE_DIR := out
+RELEASE_TAG ?= $(shell git describe --abbrev=0 2>/dev/null)
+PREVIOUS_TAG ?= $(shell git describe --abbrev=0 $(RELEASE_TAG)^ 2>/dev/null)
+RELEASE_DIR ?= out
+GIT_REPO_NAME ?= cluster-api-provider-azure
+GIT_ORG_NAME ?= kubernetes-sigs
 
 $(RELEASE_DIR):
 	mkdir -p $(RELEASE_DIR)/
@@ -460,7 +463,7 @@ release-alias-tag: # Adds the tag to the last build tag.
 
 .PHONY: release-notes
 release-notes: $(RELEASE_NOTES)
-	$(RELEASE_NOTES)
+	$(RELEASE_NOTES) --org $(GIT_ORG_NAME) --repo $(GIT_REPO_NAME)  --start-rev $(PREVIOUS_TAG) --end-rev $(RELEASE_TAG) --output release-notes-$(RELEASE_TAG).md
 
 ## --------------------------------------
 ## Development
diff --git a/api/v1alpha4/azurecluster_validation.go b/api/v1alpha4/azurecluster_validation.go
index 0d26f67cd..aa19715e8 100644
--- a/api/v1alpha4/azurecluster_validation.go
+++ b/api/v1alpha4/azurecluster_validation.go
@@ -238,7 +238,7 @@ func validateSubnetCIDR(subnetCidrBlocks []string, vnetCidrBlocks []string, fldP
 		}
 
 		if !found {
-			allErrs = append(allErrs, field.Invalid(fldPath, subnetCidr, "subnet CIDR not in vnet CIDR range"))
+			allErrs = append(allErrs, field.Invalid(fldPath, subnetCidr, fmt.Sprintf("subnet CIDR not in vnet address space: %s", vnetCidrBlocks)))
 		}
 	}
 
diff --git a/api/v1alpha4/azurecluster_webhook.go b/api/v1alpha4/azurecluster_webhook.go
index d092952ee..6af90486c 100644
--- a/api/v1alpha4/azurecluster_webhook.go
+++ b/api/v1alpha4/azurecluster_webhook.go
@@ -87,7 +87,7 @@ func (c *AzureCluster) ValidateUpdate(oldRaw runtime.Object) error {
 	if !reflect.DeepEqual(c.Spec.AzureEnvironment, old.Spec.AzureEnvironment) {
 		allErrs = append(allErrs,
 			field.Invalid(field.NewPath("spec", "AzureEnvironment"),
-				c.Spec.ResourceGroup, "field is immutable"),
+				c.Spec.AzureEnvironment, "field is immutable"),
 		)
 	}
 
diff --git a/docs/book/src/developers/development.md b/docs/book/src/developers/development.md
index 22ba9b400..9ccea8002 100644
--- a/docs/book/src/developers/development.md
+++ b/docs/book/src/developers/development.md
@@ -47,23 +47,28 @@
    - Get the latest patch version for go v1.16.
 2. Install [jq][jq]
    - `brew install jq` on macOS.
-   - `chocolatey install jq` on Windows.
+   - `sudo apt install jq` on Windows + WSL2
    - `sudo apt install jq` on Ubuntu Linux.
 3. Install [gettext][gettext] package
    - `brew install gettext && brew link --force gettext` on macOS.
-   - [install instructions][gettextwindows] on Windows.
+   - `sudo apt install gettext` on Windows + WSL2.
    - `sudo apt install gettext` on Ubuntu Linux.
 4. Install [KIND][kind]
    - `GO111MODULE="on" go get sigs.k8s.io/kind@v0.9.0`.
 5. Install [Kustomize][kustomize]
    - `brew install kustomize` on macOS.
-   - `choco install kustomize` on Windows.
-   - [install instructions][kustomizelinux] on Linux
+   - [install instructions](https://kubectl.docs.kubernetes.io/installation/kustomize/) on Windows + WSL2.
+   - [install instructions][kustomizelinux] on Linux.
 6. Install Python 3.x or 2.7.x, if neither is already installed.
 7. Install make.
+   - `brew install make` on MacOS.
+   - `sudo apt install make` on Windows + WSL2.
+   - `sudo apt install make` on Linux.
 8. Install [timeout][timeout]
    - `brew install coreutils` on macOS.
 
+When developing on Windows, it is suggested to set up the project on Windows + WSL2 and the file should be checked out on as wsl file system for better results.
+
 ### Get the source
 
 ```shell
@@ -215,7 +220,11 @@ The cluster-api management components that are deployed are configured at the `/
 
 #### Deploying a workload cluster
 
-After your kind management cluster is up and running with Tilt, you can [configure workload cluster settings](#customizing-the-cluster-deployment) and deploy a workload cluster with the following:
+⚠️ Note that when developing with `tilt` as described above, some `clusterctl` commands won't work. Specifically, `clusterctl config` and `clusterctl generate` may fail. These commands expect specific releases of CAPI and CAPZ to be installed, but the `tilt` environment dynamically updates and installs these components from your local code. `clusterctl get kubeconfig` will still work, however.
+
+After your kind management cluster is up and running with Tilt, you can [configure workload cluster settings](#customizing-the-cluster-deployment) and deploy a workload cluster by opening the `tilt` web UI and clicking the clockwise arrow icon ⟳ on a resource listed, such as "aks-aad," "ipv6," or "windows."
+
+Or you can deploy a workload cluster with the following command:
 
 ```bash
 make create-workload-cluster
diff --git a/docs/book/src/developers/releasing.md b/docs/book/src/developers/releasing.md
index 27a59b184..74c96f139 100644
--- a/docs/book/src/developers/releasing.md
+++ b/docs/book/src/developers/releasing.md
@@ -1,55 +1,47 @@
 # Release Process
 
 ## Change milestone
- -  Create a new GitHub milestone for the next release
- - Change milestone applier so new changes can be applied to the appropriate release
-      - Open a PR in https://github.com/kubernetes/test-infra to change this [line](https://github.com/kubernetes/test-infra/blob/25db54eb9d52e08c16b3601726d8f154f8741025/config/prow/plugins.yaml#L344)
-        - Example PR: https://github.com/kubernetes/test-infra/pull/16827
-
-## Prepare branch, tag and release notes
- - Identify a known good commit on the main branch
- - Fast-forward the release branch to the selected commit. :warning: Always release from the release branch and not from main!
-   - `git checkout release-0.x`
-   - `git fetch upstream`
-   - `git merge --ff-only upstream/main`
-   - `git push`
- - Create tag with git
-   - `export RELEASE_TAG=v0.4.6` (the tag of the release to be cut)
-   - `git tag -s ${RELEASE_TAG} -m "${RELEASE_TAG}"`
-	 - `-s` creates a signed tag, you must have a GPG key [added to your GitHub account](https://docs.github.com/en/enterprise/2.16/user/github/authenticating-to-github/generating-a-new-gpg-key)
-   - `git push upstream ${RELEASE_TAG}`
- - Update the file `metadata.yaml` if is a major or minor release
- - `make release` from repo, this will create the release artifacts in the `out/` folder
- - Install the `release-notes` tool according to [instructions](https://github.com/kubernetes/release/blob/master/cmd/release-notes/README.md)
- - Export GITHUB_TOKEN
- - Run the release-notes tool with the appropriate commits. Commits range from the first commit after the previous release to the new release commit.
-  ```
-  release-notes --github-org kubernetes-sigs --github-repo cluster-api-provider-azure \
-  --start-sha 1cf1ec4a1effd9340fe7370ab45b173a4979dc8f  \
-  --end-sha e843409f896981185ca31d6b4a4c939f27d975de
-  ```
- - Manually format and categorize the release notes
+
+- Create a new GitHub milestone for the next release
+- Change milestone applier so new changes can be applied to the appropriate release
+  - Open a PR in https://github.com/kubernetes/test-infra to change this [line](https://github.com/kubernetes/test-infra/blob/25db54eb9d52e08c16b3601726d8f154f8741025/config/prow/plugins.yaml#L344)
+    - Example PR: https://github.com/kubernetes/test-infra/pull/16827
+
+## Create a tag
+
+- Identify a known good commit on the main branch
+- Fast-forward the release branch to the selected commit. :warning: Always release from the release branch and not from main!
+  - `git checkout release-0.x`
+  - `git fetch upstream`
+  - `git merge --ff-only upstream/main`
+  - `git push`
+- Create tag with git
+  - `export RELEASE_TAG=v0.4.6` (the tag of the release to be cut)
+  - `git tag -s ${RELEASE_TAG} -m "${RELEASE_TAG}"`
+  - `-s` creates a signed tag, you must have a GPG key [added to your GitHub account](https://docs.github.com/en/enterprise/2.16/user/github/authenticating-to-github/generating-a-new-gpg-key)
+  - `git push upstream ${RELEASE_TAG}`
+
+This will automatically trigger a [Github Action](https://github.com/kubernetes-sigs/cluster-api-provider-azure/actions) to create a draft release.
 
 ## Promote image to prod repo
- Promote image
- - Images are built by the [post push images job](https://testgrid.k8s.io/sig-cluster-lifecycle-cluster-api-provider-azure#post-cluster-api-provider-azure-push-images)
- - Create a PR in https://github.com/kubernetes/k8s.io to add the image and tag
-   - Example PR: https://github.com/kubernetes/k8s.io/pull/1030/files
- - Location of image: https://console.cloud.google.com/gcr/images/k8s-staging-cluster-api-azure/GLOBAL/cluster-api-azure-controller?rImageListsize=30
+
+- Images are built by the [post push images job](https://testgrid.k8s.io/sig-cluster-lifecycle-cluster-api-provider-azure#post-cluster-api-provider-azure-push-images)
+- Create a PR in https://github.com/kubernetes/k8s.io to add the image and tag
+  - Example PR: https://github.com/kubernetes/k8s.io/pull/1030/files
+- Location of image: https://console.cloud.google.com/gcr/images/k8s-staging-cluster-api-azure/GLOBAL/cluster-api-azure-controller?rImageListsize=30
 
 ## Release in GitHub
- Create the GitHub release in the UI
- - Create a draft release in GitHub and associate it with the tag that was created
- - Copy paste the release notes
- - Upload [artifacts](#expected-artifacts) from the `out/` folder
- - Publish release
- - [Announce][release-announcement] the release
+
+- Manually format and categorize the release notes
+- Publish release
+- [Announce][release-announcement] the release
 
 ## Versioning
 
 cluster-api-provider-azure follows the [semantic versionining][semver] specification.
 
 Example versions:
+
 - Pre-release: `v0.1.1-alpha.1`
 - Minor release: `v0.1.0`
 - Patch release: `v0.1.1`
diff --git a/hack/install-go.sh b/hack/install-go.sh
deleted file mode 100644
index d3a68603a..000000000
--- a/hack/install-go.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright 2021 The Kubernetes Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-echo "installing apt dependencies"
-sudo apt update && sudo apt install -y curl apt-transport-https
-
-echo "setting up work dir"
-WORKDIR="$(mktemp -d)"
-pushd "$WORKDIR"
-
-trap 'rm -rf ${WORKDIR}' EXIT
-
-GOLANG_VERSION="$(curl -sS https://golang.org/VERSION?m=text)"
-echo "Downloading ${GOLANG_VERSION}"
-curl -O "https://dl.google.com/go/${GOLANG_VERSION}.linux-amd64.tar.gz"
-
-echo "unpacking go"
-sudo mkdir -p /usr/local/go
-sudo chown -R "$(whoami):$(whoami)" /usr/local/go 
-tar -xvf "${GOLANG_VERSION}.linux-amd64.tar.gz" -C /usr/local
-
-echo "Successfully installed go"


Test patch:
diff --git a/api/v1alpha4/azurecluster_validation_test.go b/api/v1alpha4/azurecluster_validation_test.go
index 0ac8eb817..fa77957c9 100644
--- a/api/v1alpha4/azurecluster_validation_test.go
+++ b/api/v1alpha4/azurecluster_validation_test.go
@@ -588,7 +588,7 @@ func TestValidateSubnetCIDR(t *testing.T) {
 				Type:     "FieldValueInvalid",
 				Field:    "subnets.cidrBlocks",
 				BadValue: "11.1.0.0/16",
-				Detail:   "subnet CIDR not in vnet CIDR range",
+				Detail:   "subnet CIDR not in vnet address space: [10.0.0.0/8]",
 			},
 		},
 		{
@@ -602,14 +602,8 @@ func TestValidateSubnetCIDR(t *testing.T) {
 		t.Run(testCase.name, func(t *testing.T) {
 			err := validateSubnetCIDR(testCase.subnetCidrBlocks, testCase.vnetCidrBlocks, field.NewPath("subnets.cidrBlocks"))
 			if testCase.wantErr {
-				g.Expect(err).NotTo(HaveLen(0))
-				found := false
-				for _, actual := range err {
-					if actual.Error() == testCase.expectedErr.Error() {
-						found = true
-					}
-				}
-				g.Expect(found).To(BeTrue())
+				// Searches for expected error in list of thrown errors
+				g.Expect(err).To(ContainElement(MatchError(testCase.expectedErr.Error())))
 			} else {
 				g.Expect(err).To(HaveLen(0))
 			}