Skip to main content

Bootstrap the ac-cicd-infra Repository from Windows 11

This page creates the initial private Aspireclan infrastructure repository from a Windows 11 workstation. The supplied ZIP contains the PowerShell scripts that create the cleaned repository scaffold, commit it to main, create and push the local, dev, qa, and prod branches, keep main as the GitHub default branch, and clone a clean local working copy.

Download the Windows repository bootstrap ZIP

The expected result is:

GitHub organization: ASPIRECLAN-LLC-Org
Repository:          ac-cicd-infra
Visibility:          private
Default branch:      main
Branches:            main, local, dev, qa, prod
Clean clone:         D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra
Checked-out branch:  main

The current infrastructure execution path is:

feature/* → dev validation → prod apply/configuration → main baseline

This bootstrap creates the repository structure only. It does not provision Proxmox VMs, configure Kubernetes, install ARC, or deploy applications.

1. Keep the ZIP in the Docusaurus static directory

Docusaurus copies files from its default static directory directly into the generated site. Keep the downloadable ZIP here:

acdocs/
├── docs/
│   └── <your-documentation-folder>/
│       └── bootstrap-ac-cicd-infra-repository.mdx
└── static/
    └── downloads/
        └── ac-cicd-infra-windows-bootstrap-v4.zip

The page uses Docusaurus useBaseUrl, so the public download link resolves correctly even when the site is deployed with a non-root baseUrl.

The public site path is:

/downloads/ac-cicd-infra-windows-bootstrap-v4.zip

From the Docusaurus project root, copy the ZIP into static/downloads:

cd D:\code\AC-Documentation-Org\acdocs

New-Item \`
  -ItemType Directory \`
  -Path ".\static\downloads" \`
  -Force | Out-Null

Copy-Item \`
  -Path "C:\Users\Manoj\Downloads\ac-cicd-infra-windows-bootstrap-v4.zip" \`
  -Destination ".\static\downloads\ac-cicd-infra-windows-bootstrap-v4.zip" \`
  -Force

Get-Item ".\static\downloads\ac-cicd-infra-windows-bootstrap-v4.zip"

Get-FileHash \`
  ".\static\downloads\ac-cicd-infra-windows-bootstrap-v4.zip" \`
  -Algorithm SHA256

The SHA-256 hash of the attached ZIP is:

SHA256
C8EA2C074103E9B4BFC6775FC347F20D74D2C058891CBABA70AD5BE25712F30E

If your local copy produces a different hash, confirm that you intentionally replaced the ZIP with a newer version before publishing the documentation.

2. Contents of the bootstrap ZIP

00-Prepare-AcCicdInfraWindows.ps1
01-New-AcCicdInfraRepository.ps1
02-Clone-AcCicdInfraRepository.ps1
99-Test-PowerShellScripts.ps1
README.md
FilePurpose
99-Test-PowerShellScripts.ps1Parses the three operational scripts with the local Windows PowerShell parser before anything is executed.
00-Prepare-AcCicdInfraWindows.ps1Checks Windows, installs Git and GitHub CLI when missing, configures Git identity, and authenticates GitHub CLI.
01-New-AcCicdInfraRepository.ps1Builds the repository in a temporary staging directory, creates the private GitHub repository, commits the scaffold, and pushes all five branches.
02-Clone-AcCicdInfraRepository.ps1Clones a clean working copy, creates local tracking branches, and returns the working copy to main.
README.mdProvides the short command sequence and expected result.

The v4 scripts retain the Windows PowerShell 5.1 compatibility fixes and update the generated scaffold to match the cleaned repository structure. They do not recreate removed placeholder trees or the obsolete 07-join-workers.yml filename.

3. Prerequisites

Before running the scripts, confirm:

  • Windows 11 is available.
  • The signed-in GitHub account can create private repositories in ASPIRECLAN-LLC-Org.
  • The repository ASPIRECLAN-LLC-Org/ac-cicd-infra does not already exist.
  • The intended Git identity is known.
  • WinGet is available if Git or GitHub CLI must be installed.
  • The target working-copy parent directory is available.

The documented working-copy location is:

D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra

4. Download and extract the ZIP

Download the ZIP using the button at the top of this page. From Windows PowerShell:

cd C:\Users\Manoj\Downloads

Expand-Archive \`
  -Path ".\ac-cicd-infra-windows-bootstrap-v4.zip" \`
  -DestinationPath ".\ac-cicd-infra-windows-bootstrap-v4" \`
  -Force

cd .\ac-cicd-infra-windows-bootstrap-v4

Get-ChildItem
Get-ChildItem -Filter "*.ps1" | Unblock-File

Verify the ZIP and display its contents when needed:

Get-FileHash \`
  ".\ac-cicd-infra-windows-bootstrap-v4.zip" \`
  -Algorithm SHA256

Add-Type -AssemblyName System.IO.Compression.FileSystem

$zipPath = Resolve-Path ".\ac-cicd-infra-windows-bootstrap-v4.zip"
$archive = [System.IO.Compression.ZipFile]::OpenRead($zipPath)

try {
    $archive.Entries |
      Select-Object FullName, Length |
      Format-Table -AutoSize
}
finally {
    $archive.Dispose()
}

5. Allow the scripts for the current PowerShell session

The execution-policy change below applies only to the current PowerShell process. It does not permanently weaken the workstation policy.

Set-ExecutionPolicy \`
  -Scope Process \`
  -ExecutionPolicy Bypass

Get-ExecutionPolicy -List

6. Parse-test all operational PowerShell scripts

Run this before any repository operation:

.\99-Test-PowerShellScripts.ps1

Expected result:

PASS: 00-Prepare-AcCicdInfraWindows.ps1
PASS: 01-New-AcCicdInfraRepository.ps1
PASS: 02-Clone-AcCicdInfraRepository.ps1

All PowerShell scripts passed parser validation.

Do not continue if any script reports FAIL.

7. Prepare Git and GitHub CLI

Run:

.\00-Prepare-AcCicdInfraWindows.ps1 \`
  -GitUserName "Manoj Nair" \`
  -GitUserEmail "aspireclan1208@gmail.com"

The script:

  1. Confirms it is running on Windows.
  2. Uses WinGet to install Git when missing.
  3. Uses WinGet to install GitHub CLI when missing.
  4. Configures the supplied Git name and email.
  5. Starts browser-based GitHub authentication when required.
  6. Configures GitHub CLI to use HTTPS for Git operations.
  7. Verifies the final authentication state.

When Git and GitHub CLI are already installed and must not be changed, use:

.\00-Prepare-AcCicdInfraWindows.ps1 \`
  -GitUserName "Manoj Nair" \`
  -GitUserEmail "aspireclan1208@gmail.com" \`
  -SkipToolInstallation

Verify the completed preparation:

git --version
gh --version
gh auth status

git config --global user.name
git config --global user.email

The GitHub account should be the account that has permission to create the organization repository.

8. Confirm that the repository does not already exist

Run:

gh repo view ASPIRECLAN-LLC-Org/ac-cicd-infra

A repository-not-found response is expected before the first creation. The repository-creation script deliberately stops when the repository already exists.

Also check the temporary staging path:

$stagingPath = Join-Path $env:TEMP "ac-cicd-infra-bootstrap"

Write-Host "Staging path: $stagingPath"
Test-Path $stagingPath

Expected before a clean first run:

False

If a failed earlier attempt left the staging directory behind and its contents are no longer needed, remove it:

Remove-Item \`
  -LiteralPath (Join-Path $env:TEMP "ac-cicd-infra-bootstrap") \`
  -Recurse \`
  -Force \`
  -ErrorAction SilentlyContinue

9. Create the private GitHub repository

Run the repository-creation script with its approved defaults:

.\01-New-AcCicdInfraRepository.ps1

The defaults are:

  • Organization: ASPIRECLAN-LLC-Org
  • Repository: ac-cicd-infra
  • Visibility: private
  • Default branch: main
  • Additional branches: local, dev, qa, prod
  • Temporary staging directory: %TEMP%\ac-cicd-infra-bootstrap

When a known disposable staging directory remains, run:

.\01-New-AcCicdInfraRepository.ps1 \`
  -ForceStagingCleanup

The parameters can also be supplied explicitly:

.\01-New-AcCicdInfraRepository.ps1 \`
  -GitHubOrganization "ASPIRECLAN-LLC-Org" \`
  -RepositoryName "ac-cicd-infra" \`
  -RepositoryDescription "Shared Proxmox, Terraform, Ansible, Kubernetes and ARC CI/CD infrastructure for Aspireclan applications."

Expected completion:

Repository creation completed successfully.

Repository:   ASPIRECLAN-LLC-Org/ac-cicd-infra
Default:      main
Branches:     main, local, dev, qa, prod

The script creates the first commit on main, pushes main, creates the other four branches from the same commit, pushes them, explicitly sets GitHub's default branch to main, and removes the temporary staging directory after success.

10. Repository structure created by the script

The bootstrap creates this cleaned initial scaffold:

ac-cicd-infra/
├── terraform/
│   ├── modules/
│   │   ├── proxmox-vm/
│   │   └── proxmox-vm-group/
│   └── stacks/
│       └── shared-k8s/
├── ansible/
│   ├── ansible.cfg
│   ├── inventories/
│   │   └── shared-k8s/
│   │       ├── hosts.ini
│   │       └── group_vars/
│   ├── playbooks/
│   │   ├── shared-k8s/
│   │   └── tenants/
│   │       └── fp/{dev,qa,prod}/
│   └── roles/
│       ├── common/
│       ├── haproxy/
│       ├── keepalived/
│       ├── containerd/
│       ├── kubernetes-common/
│       ├── kubernetes-control-plane/
│       ├── kubernetes-worker/
│       ├── arc-controller/
│       └── arc-runner-scale-set/
├── kubernetes/
│   ├── common/
│   │   └── cni/
│   └── tenants/
│       └── fp/
│           ├── organization/
│           ├── dev/{namespace,runner-scale-sets}/
│           ├── qa/{namespace,runner-scale-sets}/
│           └── prod/{namespace,runner-scale-sets}/
├── helm/
│   ├── common/
│   │   └── arc-controller/
│   └── tenants/
│       └── fp/{dev,qa,prod}/
├── .github/
│   ├── workflows/
│   │   ├── terraform-plan-shared-k8s.yml
│   │   ├── terraform-apply-shared-k8s.yml
│   │   ├── ansible-configure-shared-k8s.yml
│   │   ├── ansible-configure-load-balancer.yml
│   │   ├── ansible-configure-control-planes.yml
│   │   ├── ansible-configure-dev-workers.yml
│   │   ├── ansible-configure-qa-workers.yml
│   │   ├── ansible-configure-prod-workers.yml
│   │   ├── ansible-install-arc-controller.yml
│   │   ├── onboard-fp-github-org.yml
│   │   ├── arc-fp-web-ui-001-dev.yml
│   │   ├── arc-fp-web-ui-001-qa.yml
│   │   └── arc-fp-web-ui-001-prod.yml
│   └── CODEOWNERS
├── .editorconfig
├── .gitattributes
├── .gitignore
└── README.md

Consistency status: this tree matches the cleaned source repository and intentionally excludes the folders and files removed during cleanup.

Important characteristics:

  • Terraform manages Proxmox infrastructure definitions.
  • Ansible contains only the shared-cluster, ARC, and FP runner paths used by the current source.
  • Kubernetes and Helm contain the active shared CNI, ARC controller, FP organization, namespace, and repository scale-set paths.
  • Removed application-VM, scripts, docs, Shelvera, future-product, and separate build/deploy placeholder trees are not recreated.
  • The development worker playbook is created as 07-join-dev-workers.yml.
  • Workflow files use the active cleaned-source filenames, remain safe manual placeholders, and do not provision anything.
  • Proxmox credentials, SSH private keys, Terraform state, kubeconfig, and other secrets are not generated or committed.

11. Verify the GitHub repository and branches

Run:

gh repo view ASPIRECLAN-LLC-Org/ac-cicd-infra \`
  --json nameWithOwner,visibility,defaultBranchRef,url

gh api \`
  repos/ASPIRECLAN-LLC-Org/ac-cicd-infra/branches \`
  --jq '.[].name' 

Expected branch names, in any display order:

main
local
dev
qa
prod

Confirm that the repository visibility is PRIVATE and defaultBranchRef.name is main.

12. Clone a clean working copy

Clone into the approved Aspireclan source folder:

.\02-Clone-AcCicdInfraRepository.ps1 \`
  -CloneParent "D:\code\ASPIRECLAN-LLC-Org"

The script defaults to C:\code when -CloneParent is omitted:

.\02-Clone-AcCicdInfraRepository.ps1

If the destination already exists, the script stops rather than overwriting it. Use the force option only when the existing destination is definitely disposable:

.\02-Clone-AcCicdInfraRepository.ps1 \`
  -CloneParent "D:\code\ASPIRECLAN-LLC-Org" \`
  -ForceRemoveExistingDestination

13. Verify the cloned repository

Run:

cd D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra

git branch --show-current
git branch -vv
git branch -r
git remote -v
git status

Expected result:

Current branch: main
Local branches:
  dev
  local
* main
  prod
  qa

Working tree: clean
Remote: https://github.com/ASPIRECLAN-LLC-Org/ac-cicd-infra.git

The clone intentionally ends on main. Day-to-day infrastructure work begins by switching to dev and creating a feature branch. The retained local and qa branches are not targeted by the current shared-cluster workflows.

14. Verify the Visual Studio ignore rules

The v4 bootstrap creates the Visual Studio ignore rules from the first commit:

# Visual Studio
.vs/
*.suo
*.user
*.userosscache
*.sln.docstates
*.VC.db
*.VC.VC.opendb

Verify the committed rules and confirm that a local .vs file is ignored:

cd D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra

Select-String \`
  -Path .gitignore \`
  -Pattern '^\.vs/$','^\*\.suo$','^\*\.user$','^\*\.VC\.db$'

git check-ignore -v .vs\VSWorkspaceState.json

Expected result:

Expected:
.gitignore contains the Visual Studio rules.
git check-ignore reports that .vs/ is ignored.
No pull request is required because v4 creates these rules during bootstrap.

The ignore rules are part of the initial scaffold, so no follow-up commit or pull request is required.

15. Confirm that sensitive files are not tracked

From the cloned repository:

$sensitiveMatches = git ls-files | Select-String -Pattern \`
  '(\.tfstate|terraform\.tfvars$|kubeconfig|admin\.conf|id_ed25519|\.pem$|\.key$)'

if ($sensitiveMatches) {
    $sensitiveMatches
    throw "A sensitive file may be tracked. Review before continuing."
}

Write-Host "PASS: No known sensitive files are tracked." -ForegroundColor Green

Never commit:

  • Proxmox API tokens
  • Terraform state or plan files
  • SSH private keys
  • GitHub App private keys
  • Kubernetes kubeconfig or admin.conf
  • Ansible vault passwords
  • Deployment credentials

16. Day-to-day branch usage

Start implementation work from dev:

cd D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra

git switch dev
git pull --ff-only origin dev

git switch -c feature/<change-name>

Branch purposes:

BranchPurpose
localRetained local-only branch; not targeted by the current shared-cluster workflows.
devActive validation and Terraform-plan branch.
qaRetained promotion branch; not targeted by the current newer shared-cluster workflows.
prodApproved infrastructure apply and configuration branch.
mainProtected approved baseline.

The bootstrap does not create separate local or QA Kubernetes clusters. The active automation path is dev validation followed by prod apply/configuration.

After bootstrap, configure branch rulesets:

  • Block deletion and force pushes on all five long-lived branches.
  • Require pull requests for the protected long-lived branches after the initial bootstrap.
  • Require validation checks on dev after the real workflows have run and their exact check names are visible.
  • Restrict direct pushes to prod and main.
  • Protect the GitHub Environments used by shared Kubernetes and ARC changes.
  • Require approval for production infrastructure changes.
  • Keep main as the default branch.

Do not require placeholder workflow check names. Replace placeholder workflows first, run them once, and then select their real status-check names in the ruleset.

18. Failure handling

Repository already exists

The script stops by design. Confirm whether the existing repository is the desired repository. Do not overwrite it blindly.

Temporary staging directory exists

Inspect it first:

Get-ChildItem \`
  -Force \`
  (Join-Path $env:TEMP "ac-cicd-infra-bootstrap")

Remove-Item \`
  -LiteralPath (Join-Path $env:TEMP "ac-cicd-infra-bootstrap") \`
  -Recurse \`
  -Force

Use -ForceStagingCleanup only when those files are disposable.

Clone destination exists

Preserve unknown work by renaming the folder before cloning again:

Rename-Item \`
  -Path "D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra" \`
  -NewName "ac-cicd-infra-backup-$(Get-Date -Format yyyyMMdd-HHmmss)"

Authentication fails

Run:

gh auth logout
gh auth login --hostname github.com --git-protocol https --web
gh auth setup-git
gh auth status

Organization repository creation is denied

Confirm that the authenticated GitHub account is allowed to create repositories in ASPIRECLAN-LLC-Org. Organization policy may restrict repository creation to owners.

PowerShell parser test fails

Stop and replace the local extracted ZIP with the published v4 ZIP. Do not edit around a parser failure without reviewing the exact script difference.

From the Docusaurus project root:

cd D:\code\AC-Documentation-Org\acdocs

npm install
npm run start

Open this documentation page and click the download button. A direct local-development test can also use:

$downloadUrl = "http://localhost:3000/downloads/ac-cicd-infra-windows-bootstrap-v4.zip"
$testFile = Join-Path $env:TEMP "ac-cicd-infra-windows-bootstrap-v4-test.zip"

Invoke-WebRequest \`
  -Uri $downloadUrl \`
  -OutFile $testFile

Get-FileHash $testFile -Algorithm SHA256
Remove-Item $testFile

The downloaded test ZIP should produce the same SHA-256 hash shown earlier.

20. Successful completion state

Private repository created: ASPIRECLAN-LLC-Org/ac-cicd-infra
Default GitHub branch: main
Branches pushed: main, local, dev, qa, prod
Working copy cloned to: D:\code\ASPIRECLAN-LLC-Org\ac-cicd-infra
Working copy checked out on: main
Initial repository content: cleaned implementation scaffold only
Scaffold consistency: aligned with the cleaned ac-cicd-infra source structure
Development worker playbook: 07-join-dev-workers.yml
Unused application-vm, scripts, docs, Shelvera, and future-product placeholders: not created
Infrastructure provisioned by bootstrap: none
Secrets committed: none
Terraform state committed: none

The next implementation page can now replace the scaffolded Terraform and Ansible placeholders with the approved shared Kubernetes infrastructure, starting from a feature branch created from dev.