├── .gitattributes ├── samples ├── crypt │ ├── devops │ │ ├── storeFor │ │ ├── crypt │ │ │ └── AES_CRYPT │ │ ├── cryptLocal │ │ │ └── WINDOWS_PASSWORD │ │ ├── custom │ │ │ ├── crypt-test.yml │ │ │ └── properties.varchk │ │ ├── .gitignore │ │ ├── properties.cm │ │ ├── CDAF.solution │ │ └── tasksRun.tsk │ └── .gitignore ├── .gitignore ├── all │ ├── automation-solution │ │ ├── storeForLocal │ │ ├── storeForRemote │ │ ├── crypt │ │ │ └── secrets.crypt │ │ ├── cryptLocal │ │ │ └── WINDOWS_PASSWORD │ │ ├── propertiesForRemoteTasks │ │ │ ├── WINDOWS_LOCALHOST_NTLM │ │ │ ├── USER_PASSWORD_LOCALHOST │ │ │ └── VAGRANT_CERTIFICATE_DECRYPT │ │ ├── customLocal │ │ │ └── properties.varchk │ │ ├── propertiesForLocalTasks │ │ │ └── WORKGROUP_LOCAL │ │ ├── CDAF.solution │ │ ├── custom │ │ │ ├── slack.ps1 │ │ │ └── example.yaml │ │ ├── properties.cm │ │ ├── tasksRunRemote.tsk │ │ ├── storeForArtifact.txt │ │ └── tasksRunLocal.tsk │ ├── project │ │ └── build.tsk │ ├── .gitignore │ ├── readme.md │ └── build.tsk ├── custom │ ├── automation-solution │ │ ├── storeForLocal │ │ ├── properties.cm │ │ ├── CDAF.solution │ │ ├── tasksRunLocal.tsk │ │ └── customLocal │ │ │ └── customDeploy.ps1 │ └── .gitignore ├── minimal-build │ ├── automation-solution │ │ ├── storeForLocal │ │ ├── customLocal │ │ │ └── properties.varchk │ │ ├── CDAF.solution │ │ ├── properties.cm │ │ ├── build.tsk │ │ └── tasksRunLocal.tsk │ ├── solution.properties │ ├── build.tsk │ └── .gitignore ├── targetlessCD │ ├── automation-solution │ │ ├── storeForLocal │ │ ├── CDAF.solution │ │ ├── customLocal │ │ │ ├── containerTest.tsk │ │ │ ├── Dockerfile │ │ │ ├── bootstrapTarget.ps1 │ │ │ └── compose.tsk │ │ └── properties.cm │ ├── .gitignore │ ├── compose │ │ ├── docker-compose.yml │ │ └── test │ │ │ └── Dockerfile │ └── readme.md ├── containerBuild │ ├── build.tsk │ ├── .gitignore │ └── automation-solution │ │ └── CDAF.solution ├── containerBuild-custom-image │ ├── build.tsk │ ├── .gitignore │ ├── automation-solution │ │ ├── CDAF.solution │ │ └── bootstrapAgent.ps1 │ ├── Readme.md │ └── Dockerfile ├── log-image │ ├── solution │ │ ├── CDAF.solution │ │ ├── tasksRun.tsk │ │ └── properties.cm │ └── .gitignore ├── containerDeploy │ ├── automation-solution │ │ ├── storeForRemote │ │ ├── properties.cm │ │ ├── customRemote │ │ │ └── deploy.tsk │ │ └── CDAF.solution │ └── .gitignore ├── deliveryEnv.ps1 ├── imageBuild │ ├── automation-solution │ │ ├── customLocal │ │ │ └── immutable.tsk │ │ ├── properties.cm │ │ └── CDAF.solution │ └── .gitignore ├── containerDeploy-custom-image │ ├── automation-solution │ │ ├── storeForRemote │ │ ├── storeForLocal │ │ ├── customRemote │ │ │ └── deploy.tsk │ │ ├── properties.cm │ │ └── CDAF.solution │ ├── Dockerfile │ ├── .gitignore │ └── containerDeploy │ │ ├── settings.xml │ │ ├── Dockerfile │ │ └── bootstrapAgent.ps1 ├── minimal │ ├── .gitignore │ └── automation-solution │ │ └── CDAF.solution ├── pre-post-processes │ ├── automation-solution │ │ ├── example.yaml │ │ ├── CDAF.solution │ │ ├── wrap.tsk │ │ ├── package.tsk │ │ ├── postbuild.tsk │ │ ├── prebuild.tsk │ │ └── build.tsk │ └── .gitignore ├── imageBuild-custom-image │ ├── .gitignore │ └── automation-solution │ │ ├── customLocal │ │ └── Dockerfile │ │ └── CDAF.solution ├── feature-branch-environments │ ├── automation-solution │ │ ├── feature-branch.properties │ │ ├── CDAF.solution │ │ ├── properties.cm │ │ └── tasksRunLocal.tsk │ └── .gitignore ├── cd.ps1 ├── deliveryScript.ps1 └── executeSamples.ps1 ├── automation ├── powershell.lnk ├── buildandpackage │ ├── storeArtifacts.ps1 │ └── loadVSenv.ps1 ├── CDAF.windows ├── remote │ ├── getProperty.ps1 │ ├── extract.ps1 │ ├── deploy.bat │ ├── push.bat │ ├── push.ps1 │ ├── fixACLs.ps1 │ ├── logWatch.ps1 │ └── winrmtest.ps1 ├── Readme.md ├── .gitignore ├── local │ ├── push.ps1 │ ├── RemoteTest.ps1 │ ├── deploy.ps1 │ ├── remotePackageManagement.ps1 │ ├── localTasksTarget.ps1 │ ├── copy.ps1 │ ├── copyTemplate.ps1 │ ├── embed.ps1 │ └── remoteTasks.ps1 ├── cdEmulate.bat ├── entry.bat ├── processor │ └── delivery.bat ├── ci.bat └── badge.svg ├── provisioning ├── ADGroupMember.ps1 ├── openFirewallPort.ps1 ├── EnableClientRemoting.ps1 ├── EnableServerRemoting.ps1 ├── readme.md ├── trustedHosts.ps1 ├── runner.bat ├── removeFile.ps1 ├── EnableFileAndPrintSharing.ps1 ├── nextFreePort.ps1 ├── setProductKey.ps1 ├── setStaticIP.ps1 ├── installEXE.ps1 ├── sqlLocalDBInstance.ps1 ├── applyWindowsUpdates.ps1 ├── CredDelegation.ps1 ├── encypt.ps1 ├── setWinRM.ps1 ├── setSPN.ps1 ├── addProxy.ps1 ├── WIF.ps1 ├── SDK.ps1 ├── setenv.ps1 ├── IISPoolAccount.ps1 ├── agent.ps1 ├── computerCertificate.ps1 ├── sqlAuthMode.ps1 ├── addVSTSPackageCred.ps1 ├── removeUser.ps1 ├── mkdir.ps1 ├── addFeature.ps1 ├── WIFSDK.ps1 ├── sqlCreateDB.ps1 ├── GetExecutable.ps1 ├── setInternetProxy.ps1 ├── addUserToLocalGroup.ps1 ├── addPath.ps1 ├── installAzureRM.ps1 ├── addHOSTS.ps1 ├── installMSU.ps1 └── sqlAddUserDB.ps1 ├── orchestration ├── ado │ ├── Multi-stage │ │ ├── .cdaf │ │ │ └── CDAF.solution │ │ ├── templates │ │ │ ├── azure-pipelines-dockerhub-template.yml │ │ │ ├── azure-pipelines-terraform-template.yml │ │ │ ├── azure-pipelines-deployment-template.yml │ │ │ └── azure-pipelines-build-template.yml │ │ └── azure-pipelines.yml │ └── CI-Only │ │ └── azure-pipelines.yml ├── buildmaster │ ├── deploy │ └── build ├── bamboo-specs │ ├── v1 │ │ └── bamboo.yml │ └── bamboo.yml ├── vagrant-box │ └── Vagrantfile ├── jenkins │ ├── jenkins-scripted-pipeline │ │ └── Jenkinsfile │ └── jenkins-declaritive-pipeline │ │ └── Jenkinsfile ├── vagrant-test │ └── Vagrantfile ├── gitlab │ └── .gitlab-ci.yml └── bitbucket │ └── bitbucket-pipelines.yml ├── .project ├── .gitignore ├── Readme.md ├── LICENSE.md └── .github └── workflows └── delivery.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | * -text 2 | -------------------------------------------------------------------------------- /samples/crypt/devops/storeFor: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/.gitignore: -------------------------------------------------------------------------------- 1 | /build.binary 2 | -------------------------------------------------------------------------------- /samples/all/automation-solution/storeForLocal: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/all/automation-solution/storeForRemote: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /samples/custom/automation-solution/storeForLocal: -------------------------------------------------------------------------------- 1 | example.yaml -------------------------------------------------------------------------------- /samples/minimal-build/automation-solution/storeForLocal: -------------------------------------------------------------------------------- 1 | example.yaml -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/storeForLocal: -------------------------------------------------------------------------------- 1 | # TargetlessCD 2 | compose 3 | -------------------------------------------------------------------------------- /automation/powershell.lnk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/automation/powershell.lnk -------------------------------------------------------------------------------- /samples/all/project/build.tsk: -------------------------------------------------------------------------------- 1 | echo "Child Project build verification" 2 | 3 | Get-ChildItem env: 4 | -------------------------------------------------------------------------------- /samples/containerBuild/build.tsk: -------------------------------------------------------------------------------- 1 | echo "Apply build activity here, which will execute in your container" -------------------------------------------------------------------------------- /provisioning/ADGroupMember.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/provisioning/ADGroupMember.ps1 -------------------------------------------------------------------------------- /provisioning/openFirewallPort.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/provisioning/openFirewallPort.ps1 -------------------------------------------------------------------------------- /samples/containerBuild-custom-image/build.tsk: -------------------------------------------------------------------------------- 1 | echo "Apply build activity here, which will execute in your container" -------------------------------------------------------------------------------- /provisioning/EnableClientRemoting.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/provisioning/EnableClientRemoting.ps1 -------------------------------------------------------------------------------- /provisioning/EnableServerRemoting.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/provisioning/EnableServerRemoting.ps1 -------------------------------------------------------------------------------- /samples/crypt/devops/crypt/AES_CRYPT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/samples/crypt/devops/crypt/AES_CRYPT -------------------------------------------------------------------------------- /samples/log-image/solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | solutionName=log-image 2 | artifactPrefix=0.0 3 | defaultEnvironment=WINDOWS 4 | -------------------------------------------------------------------------------- /samples/containerDeploy/automation-solution/storeForRemote: -------------------------------------------------------------------------------- 1 | # The containerDeploy assets are executed in the remote context 2 | -------------------------------------------------------------------------------- /samples/deliveryEnv.ps1: -------------------------------------------------------------------------------- 1 | # This is an example script which only return WINDOWS, i.e. the on-domain default 2 | return 'WINDOWS' -------------------------------------------------------------------------------- /samples/imageBuild/automation-solution/customLocal/immutable.tsk: -------------------------------------------------------------------------------- 1 | echo "Deploy your software artefacts into the immutable image." -------------------------------------------------------------------------------- /samples/imageBuild/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target deployTaskOverride 2 | local IMMUTABLE immutable.tsk 3 | -------------------------------------------------------------------------------- /automation/buildandpackage/storeArtifacts.ps1: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/automation/buildandpackage/storeArtifacts.ps1 -------------------------------------------------------------------------------- /orchestration/ado/Multi-stage/.cdaf/CDAF.solution: -------------------------------------------------------------------------------- 1 | solutionName=azuredevops.multistage 2 | artifactPrefix=0.0 3 | # defaultBranch=main 4 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/automation-solution/storeForRemote: -------------------------------------------------------------------------------- 1 | # The containerDeploy assets are executed in the remote context 2 | -------------------------------------------------------------------------------- /samples/containerBuild-custom-image/.gitignore: -------------------------------------------------------------------------------- 1 | /automation/ 2 | /container-build/ 3 | /TasksLocal/ 4 | /container-build-*.zip 5 | /release.ps1 6 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/automation-solution/storeForLocal: -------------------------------------------------------------------------------- 1 | # Store containerDeploy if constructing a custom image 2 | containerDeploy -------------------------------------------------------------------------------- /samples/crypt/devops/cryptLocal/WINDOWS_PASSWORD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/samples/crypt/devops/cryptLocal/WINDOWS_PASSWORD -------------------------------------------------------------------------------- /samples/log-image/solution/tasksRun.tsk: -------------------------------------------------------------------------------- 1 | echo "Download an image" 2 | curl.exe -s -O $uri 3 | 4 | echo "Write image to Log" 5 | IMGTXT $filename 6 | -------------------------------------------------------------------------------- /samples/all/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /myProduct-*.zip 3 | /bin.bat 4 | /propertiesForLocalTasks/ 5 | /propertiesForRemoteTasks/ 6 | /release.ps1 7 | -------------------------------------------------------------------------------- /samples/all/automation-solution/crypt/secrets.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/samples/all/automation-solution/crypt/secrets.crypt -------------------------------------------------------------------------------- /samples/containerBuild/.gitignore: -------------------------------------------------------------------------------- 1 | /automation/ 2 | /container-build/ 3 | /TasksLocal/ 4 | /container-build-*.zip 5 | /release.ps1 6 | /Dockerfile 7 | -------------------------------------------------------------------------------- /samples/minimal/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /minimal-package-*.zip 3 | /minimal-package-*.tar.gz 4 | /bin.bat 5 | /release.ps1 6 | /minimal-package-*/ 7 | -------------------------------------------------------------------------------- /samples/imageBuild/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /index.html 3 | /manifest.txt 4 | /storeForLocal_manifest.txt 5 | /app/ 6 | /imagebuild-*.zip 7 | /release.ps1 8 | -------------------------------------------------------------------------------- /samples/all/automation-solution/cryptLocal/WINDOWS_PASSWORD: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/samples/all/automation-solution/cryptLocal/WINDOWS_PASSWORD -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/example.yaml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdaf/windows/HEAD/samples/pre-post-processes/automation-solution/example.yaml -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/automation-solution/customRemote/deploy.tsk: -------------------------------------------------------------------------------- 1 | echo "Here we execute the CLI or REST deployment steps" 2 | 3 | anypoint-cli-v4 --version -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | solutionName=targetless-cd 2 | artifactPrefix=0.0 3 | 4 | buildImage=cdaf/iis 5 | runtimeImage=cdaf/windows 6 | -------------------------------------------------------------------------------- /samples/custom/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target deployScriptOverride 2 | local WINDOWS customDeploy.ps1 3 | local WORKGROUP customDeploy.ps1 4 | -------------------------------------------------------------------------------- /samples/imageBuild-custom-image/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /index.html 3 | /manifest.txt 4 | /storeForLocal_manifest.txt 5 | /app/ 6 | /imagebuild-*.zip 7 | /release.ps1 8 | -------------------------------------------------------------------------------- /samples/minimal-build/automation-solution/customLocal/properties.varchk: -------------------------------------------------------------------------------- 1 | NON_EXIST=optional 2 | 3 | # Verify variable is populated and log the checksum value 4 | HOME=secret 5 | -------------------------------------------------------------------------------- /samples/all/automation-solution/propertiesForRemoteTasks/WINDOWS_LOCALHOST_NTLM: -------------------------------------------------------------------------------- 1 | # Mandatory properties to land package on host 2 | deployHost=localhost 3 | deployLand=c:\deploy 4 | -------------------------------------------------------------------------------- /samples/all/automation-solution/customLocal/properties.varchk: -------------------------------------------------------------------------------- 1 | env:NON_EXIST=optional 2 | 3 | # Verify variable is populated and log the checksum value 4 | env:COMPUTERNAME=secret 5 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target deployTaskOverride 2 | container WINDOWS deploy.tsk 3 | container WORKGROUP deploy.tsk 4 | -------------------------------------------------------------------------------- /samples/all/automation-solution/propertiesForLocalTasks/WORKGROUP_LOCAL: -------------------------------------------------------------------------------- 1 | # Use the same process as loop-back connection (WINDOWS) but on the localhost 2 | deployTaskOverride=tasksRunRemote.tsk 3 | -------------------------------------------------------------------------------- /samples/all/automation-solution/propertiesForRemoteTasks/USER_PASSWORD_LOCALHOST: -------------------------------------------------------------------------------- 1 | # Mandatory properties to land package on host 2 | deployHost=localhost 3 | remoteUser=vagrant 4 | remotePass=vagrant -------------------------------------------------------------------------------- /samples/log-image/solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target filename uri 2 | local WORKGROUP JPEG_example_flower.jpg https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg 3 | -------------------------------------------------------------------------------- /samples/minimal-build/solution.properties: -------------------------------------------------------------------------------- 1 | PROJECT= 2 | REVISION=feature 3 | AUTOMATIONROOT=/mnt/c/Users/jules/git/linux/automation 4 | SOLUTIONROOT=/mnt/c/Users/jules/git/linux/samples/minimal-build/automation-solution 5 | -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/customLocal/containerTest.tsk: -------------------------------------------------------------------------------- 1 | curl.exe --silent target 2 | 3 | $status = curl.exe --silent -w '%{http_code}' target -o output.log 4 | if ( $status -ne '200' ) { exit $status } -------------------------------------------------------------------------------- /samples/containerBuild/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Container Build Sample 2 | solutionName=container-build-minimal 3 | artifactPrefix=0.0 4 | 5 | containerImage=cdaf/windows 6 | CDAF_DOCKER_REQUIRED=yes 7 | -------------------------------------------------------------------------------- /samples/feature-branch-environments/automation-solution/feature-branch.properties: -------------------------------------------------------------------------------- 1 | # Separate environments for features and bugs 2 | feature=DEV1 3 | bugfix=DEV2 4 | 5 | # Hotfixes deploy to all environments 6 | hotfix=DEV1 7 | hotfix=DEV2 -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Sample of Optional Processes 2 | solutionName=pre-post-processes 3 | 4 | artifactPrefix=0.0 5 | packageFeatures=minimal 6 | 7 | processSequence=localTasks.ps1 8 | -------------------------------------------------------------------------------- /samples/minimal-build/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Simple Build and Minimal Release Package Process 2 | solutionName=minimal-build 3 | 4 | artifactPrefix=0.0 5 | packageFeatures=minimal 6 | 7 | processSequence=localTasks.ps1 8 | -------------------------------------------------------------------------------- /samples/all/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | # Template Solution Properties file 2 | # If using symantic versioning, append build number at the end of version 3 | artifactPrefix=0.1 4 | productName=My Product Name 5 | solutionName=myProduct 6 | -------------------------------------------------------------------------------- /samples/minimal/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Minimal Release Package 2 | solutionName=minimal-package 3 | 4 | artifactPrefix=0.0 5 | packageFeatures=minimal 6 | packageMethod=tarball 7 | 8 | processSequence=localTasks.ps1 9 | -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/wrap.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "SOLUTIONROOT = $SOLUTIONROOT" 3 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 4 | echo "CDAF_CORE = $CDAF_CORE" 5 | 6 | echo "Post-package Tasks" 7 | -------------------------------------------------------------------------------- /samples/custom/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Custom Build and Deployment Scripts 2 | solutionName=custom 3 | 4 | artifactPrefix=0.0 5 | packageFeatures=minimal 6 | packageMethod=tarball 7 | 8 | processSequence=localTasks.ps1 9 | -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/package.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "SOLUTIONROOT = $SOLUTIONROOT" 3 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 4 | echo "CDAF_CORE = $CDAF_CORE" 5 | 6 | echo "Pre-package Tasks" 7 | -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/postbuild.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "SOLUTIONROOT = $SOLUTIONROOT" 3 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 4 | echo "CDAF_CORE = $CDAF_CORE" 5 | 6 | echo "Post Build Tasks" 7 | -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/prebuild.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "SOLUTIONROOT = $SOLUTIONROOT" 3 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 4 | echo "CDAF_CORE = $CDAF_CORE" 5 | 6 | echo "Pre-Build Tasks" 7 | -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target deployTaskOverride 2 | local DOCKER compose.tsk 3 | local WINDOWS compose.tsk 4 | local WORKGROUP compose.tsk 5 | 6 | local AUTO_TEST containerTest.tsk 7 | -------------------------------------------------------------------------------- /orchestration/buildmaster/deploy: -------------------------------------------------------------------------------- 1 | ##AH:UseTextMode 2 | 3 | 4 | Deploy-Artifact TasksLocal 5 | ( 6 | To: $WorkingDirectory 7 | ); 8 | 9 | Execute-PowerShell >>cd $WorkingDirectory 10 | .\TasksLocal\delivery.bat $EnvironmentName >>; 11 | -------------------------------------------------------------------------------- /samples/minimal-build/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target literal zero integer var_load 2 | local WINDOWS "Hello WINDOWS" '0' 1 $env:USERNAME 3 | local WORKGROUP "Hello WORKGROUP" '0' 2 $env:USERNAME 4 | -------------------------------------------------------------------------------- /samples/crypt/devops/custom/crypt-test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | application: 3 | admin-password: "%secret1%" 4 | user-password: "@dbuserpassword@" 5 | database: 6 | target: "%deployHost%" 7 | user: "%dbreaderwriter%" 8 | password: "%secret2%" 9 | -------------------------------------------------------------------------------- /samples/feature-branch-environments/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Deploying from Feature Branch Based on Branch Name 2 | solutionName=feature-branch-environments 3 | 4 | artifactPrefix=0.0 5 | packageFeatures=minimal 6 | 7 | processSequence=localTasks.ps1 8 | -------------------------------------------------------------------------------- /samples/minimal-build/automation-solution/build.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "PROJECT = $PROJECT" 3 | echo "SOLUTIONROOT = $SOLUTIONROOT" 4 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 5 | echo "CDAF_CORE = $CDAF_CORE" 6 | 7 | echo "Project Level Build" 8 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | _CDAF Github PowerShell 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /samples/feature-branch-environments/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target usage 2 | local LINUX "Default environment" 3 | local DEV1 "Feature branch environment for feature or hotfix branch" 4 | local DEV2 "Feature branch environment for bugfix or hotfix branch" 5 | -------------------------------------------------------------------------------- /samples/all/automation-solution/propertiesForRemoteTasks/VAGRANT_CERTIFICATE_DECRYPT: -------------------------------------------------------------------------------- 1 | # Mandatory properties to land package on host 2 | deployHost=windows-1.mshome.net 3 | deployLand=c:\deploy 4 | remoteUser=vagrant 5 | remoteCred=WINDOWS_PASSWORD 6 | decryptThb=1C5A22D1DA540F210122BB63EB8F38ABBBB9009A 7 | -------------------------------------------------------------------------------- /automation/CDAF.windows: -------------------------------------------------------------------------------- 1 | # Do not make customisation or configuration changes in these folders, copy the solution folder 2 | # and apply configuration changes that are specific to your solution. 3 | productVersion=3.0.0.b 4 | productName=Continuous Delivery Automation Framework 5 | solutionName=WU-CDM 6 | -------------------------------------------------------------------------------- /samples/feature-branch-environments/automation-solution/tasksRunLocal.tsk: -------------------------------------------------------------------------------- 1 | echo "In this example, only branch names containing 'feature', 'bugfix' or 'hotfix' will execute from etnry.sh," 2 | echo "This configuration has no affect on cdEmulate execution." 3 | 4 | PROPLD manifest.txt 5 | 6 | echo "deploying branch name $REVISION to $TARGET" 7 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/Dockerfile: -------------------------------------------------------------------------------- 1 | # DOCKER-VERSION 1.2.0 2 | ARG CONTAINER_IMAGE 3 | FROM ${CONTAINER_IMAGE} 4 | 5 | WORKDIR /solution/workspace 6 | 7 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference = 'Continue';"] 8 | 9 | CMD ["Wait-Event"] 10 | -------------------------------------------------------------------------------- /samples/pre-post-processes/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip -------------------------------------------------------------------------------- /samples/crypt/devops/custom/properties.varchk: -------------------------------------------------------------------------------- 1 | env:NON_EXIST=optional 2 | 3 | # Verify variable is populated and log the checksum value 4 | env:AES_KEY=secret 5 | 6 | # Verify variable is populated, and the SHA256 matches, support literal or variable 7 | env:AES_KEY=90BF7460FFDFE121C41AAFDF6B7D33EB08ACD0736D8B0A0B461E595E32DE26F5 8 | env:AES_KEY=$env:AES_KEY_MASK -------------------------------------------------------------------------------- /samples/log-image/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip -------------------------------------------------------------------------------- /samples/targetlessCD/.gitignore: -------------------------------------------------------------------------------- 1 | /cdaf/ 2 | /TasksLocal/ 3 | /TasksRemote/ 4 | /projectDirectories.txt 5 | /manifest.txt 6 | /storeFor_manifest.txt 7 | /storeForLocal_manifest.txt 8 | /storeForRemote_manifest.txt 9 | /projectsToBuild.txt 10 | /propertiesForLocalTasks/ 11 | /propertiesForRemoteTasks/ 12 | /propertiesForContainerTasks/ 13 | /release.ps1 14 | /*.zip -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip 14 | /*.tar.gz 15 | -------------------------------------------------------------------------------- /samples/containerDeploy/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip 14 | /*.tar.gz 15 | -------------------------------------------------------------------------------- /automation/remote/getProperty.ps1: -------------------------------------------------------------------------------- 1 | $PROP_FILE = $args[0] 2 | $PROP_NAME = $args[1] 3 | 4 | # Brute force property retrieval, comment lines are not explicitely ignored, simply omitted as they won't match the property name sought 5 | Foreach ($ROW in get-content $PROP_FILE) { 6 | $test = $ROW -split '=', 2 7 | if ( $test[0] -eq $PROP_NAME ) { 8 | return $test[1] 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /samples/custom/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip 14 | /*.tar.gz 15 | /runtime.ps1 16 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip 14 | /*.tar.gz 15 | -------------------------------------------------------------------------------- /automation/Readme.md: -------------------------------------------------------------------------------- 1 | # Continuous Delivery Automation Framework (CDAF) 2 | 3 | For principles and usage guidance see [https://cdaf.io](https://cdaf.io/10-cdaf/index.html). 4 | 5 | For the complete set of samples and provisioning helpers, see [GitHub](https://github.com/cdaf/windows). 6 | 7 | For related blog, see [LinkedIn articles](https://www.linkedin.com/in/jules-clements-842b589/recent-activity/articles/). 8 | -------------------------------------------------------------------------------- /samples/feature-branch-environments/.gitignore: -------------------------------------------------------------------------------- 1 | /TasksLocal/ 2 | /TasksRemote/ 3 | /projectDirectories.txt 4 | /manifest.txt 5 | /storeFor_manifest.txt 6 | /storeForLocal_manifest.txt 7 | /storeForRemote_manifest.txt 8 | /projectsToBuild.txt 9 | /propertiesForLocalTasks/ 10 | /propertiesForRemoteTasks/ 11 | /propertiesForContainerTasks/ 12 | /release.ps1 13 | /*.zip 14 | /*.tar.gz 15 | /runtime.ps1 16 | -------------------------------------------------------------------------------- /samples/all/automation-solution/custom/slack.ps1: -------------------------------------------------------------------------------- 1 | Add-Type -AssemblyName System.Net.Http 2 | $http = New-Object -TypeName System.Net.Http.Httpclient 3 | $message = "Hello world." 4 | $httpMessage = "{""text"": """ + $message + """}"; 5 | $content = New-Object -TypeName System.Net.Http.StringContent($httpMessage) 6 | $httpResult = $http.PostAsync("https://hooks.slack.com/services/your_channel_url_here", $content).Result 7 | -------------------------------------------------------------------------------- /samples/containerBuild-custom-image/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Container Build Sample 2 | solutionName=container-build 3 | artifactPrefix=0.0 4 | 5 | containerBuild=& ${AUTOMATIONROOT}/processor/containerBuild.ps1 $SOLUTION $BUILDNUMBER $REVISION $ACTION 6 | containerImage=cdaf/windows 7 | CDAF_DOCKER_REQUIRED=yes 8 | 9 | packageFeatures=minimal 10 | 11 | processSequence=localTasks.ps1 12 | -------------------------------------------------------------------------------- /samples/minimal-build/build.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "SOLUTIONROOT = $SOLUTIONROOT" 3 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 4 | echo "CDAF_CORE = $CDAF_CORE" 5 | 6 | echo "Solution Level Build" 7 | 8 | echo '---' > example.yaml 9 | echo ' application:' >> example.yaml 10 | echo ' message: "%literal%"' >> example.yaml 11 | echo ' secret: "@secret@"' >> example.yaml 12 | cat example.yaml -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | [![License: LGPL v3](https://img.shields.io/badge/License-LGPL%20v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0) 2 | [![cdaf version](automation/badge.svg)](http://cdaf.io) 3 | 4 | # Continuous Delivery Automation Framework for Windows 5 | 6 | For published documentation see https://docs.cdaf.io/ 7 | 8 | For core product see automation directory and see also samples directory for some patterns. 9 | 10 | -------------------------------------------------------------------------------- /orchestration/buildmaster/build: -------------------------------------------------------------------------------- 1 | ##AH:UseTextMode 2 | 3 | 4 | Git::Get-Source 5 | ( 6 | Credentials: Bonobo, 7 | DiskPath: $WorkingDirectory 8 | ); 9 | 10 | Execute-PowerShell >>cd $WorkingDirectory 11 | .\automation\ci.bat $BuildNumber>>; 12 | 13 | Create-Artifact Package 14 | ( 15 | Include: *.zip 16 | ); 17 | 18 | Create-Artifact TasksLocal 19 | ( 20 | Include: "TasksLocal/**" 21 | ); 22 | -------------------------------------------------------------------------------- /samples/minimal-build/.gitignore: -------------------------------------------------------------------------------- 1 | /buildnumber.counter 2 | /TasksLocal/ 3 | /TasksRemote/ 4 | /targetList 5 | /projectDirectories.txt 6 | /manifest.txt 7 | /storeFor_manifest.txt 8 | /storeForLocal_manifest.txt 9 | /storeForRemote_manifest.txt 10 | /projectsToBuild.txt 11 | /propertiesForLocalTasks/ 12 | /propertiesForRemoteTasks/ 13 | /propertiesForContainerTasks/ 14 | /*.gz 15 | /release.ps1 16 | /example.yaml 17 | 18 | /minimal-build-* 19 | -------------------------------------------------------------------------------- /samples/pre-post-processes/automation-solution/build.tsk: -------------------------------------------------------------------------------- 1 | echo "REVISION = $REVISION" 2 | echo "SOLUTIONROOT = $SOLUTIONROOT" 3 | echo "AUTOMATIONROOT = $AUTOMATIONROOT" 4 | echo "CDAF_CORE = $CDAF_CORE" 5 | 6 | echo "Solution Level Build" 7 | 8 | echo '---' > example.yaml 9 | echo ' application:' >> example.yaml 10 | echo ' message: "%literal%"' >> example.yaml 11 | echo ' secret: "@secret@"' >> example.yaml 12 | cat example.yaml -------------------------------------------------------------------------------- /samples/all/readme.md: -------------------------------------------------------------------------------- 1 | # All CDAF Core Features 2 | 3 | To avoid execution of Remote Tasks 4 | 5 | $env:CDAF_DELIVERY='WORKGROUP' 6 | 7 | To execute Remote Tasks, configure remote loop-back access to teh localhost. 8 | 9 | ..\..\automation\provisioning\mkdir.ps1 C:\deploy 10 | ..\..\automation\provisioning\CredSSP.ps1 server 11 | 12 | ..\..\automation\provisioning\trustedHosts.ps1 * 13 | ..\..\automation\provisioning\CredSSP.ps1 client -------------------------------------------------------------------------------- /automation/.gitignore: -------------------------------------------------------------------------------- 1 | # CDAF Working Files 2 | /TasksLocal/ 3 | /TasksRemote/ 4 | /projectDirectories.txt 5 | /manifest.txt 6 | /storeFor_manifest.txt 7 | /storeForLocal_manifest.txt 8 | /storeForRemote_manifest.txt 9 | /projectsToBuild.txt 10 | /propertiesForLocalTasks/ 11 | /propertiesForRemoteTasks/ 12 | /propertiesForContainerTasks/ 13 | /release.ps1 14 | /*.zip 15 | /*.tar.gz 16 | /bin/ 17 | 18 | # Exclude CDAF Copy for containerBuild process 19 | # /automation/ -------------------------------------------------------------------------------- /samples/containerDeploy/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target deployTaskOverride filename uri 2 | container WINDOWS deploy.tsk JPEG_example_flower.jpg https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg 3 | container WORKGROUP deploy.tsk JPEG_example_flower.jpg https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg 4 | -------------------------------------------------------------------------------- /samples/crypt/.gitignore: -------------------------------------------------------------------------------- 1 | # CDAF Working Files 2 | /TasksLocal/ 3 | /TasksRemote/ 4 | /projectDirectories.txt 5 | /manifest.txt 6 | /storeFor_manifest.txt 7 | /storeForLocal_manifest.txt 8 | /storeForRemote_manifest.txt 9 | /projectsToBuild.txt 10 | /propertiesForLocalTasks/ 11 | /propertiesForRemoteTasks/ 12 | /propertiesForContainerTasks/ 13 | /release.ps1 14 | /*.zip 15 | /*.tar.gz 16 | /bin/ 17 | 18 | # Exclude CDAF Copy for containerBuild process 19 | # /automation/ -------------------------------------------------------------------------------- /samples/crypt/devops/.gitignore: -------------------------------------------------------------------------------- 1 | # CDAF Working Files 2 | /TasksLocal/ 3 | /TasksRemote/ 4 | /projectDirectories.txt 5 | /manifest.txt 6 | /storeFor_manifest.txt 7 | /storeForLocal_manifest.txt 8 | /storeForRemote_manifest.txt 9 | /projectsToBuild.txt 10 | /propertiesForLocalTasks/ 11 | /propertiesForRemoteTasks/ 12 | /propertiesForContainerTasks/ 13 | /release.ps1 14 | /*.zip 15 | /*.tar.gz 16 | /bin/ 17 | 18 | # Exclude CDAF Copy for containerBuild process 19 | # /automation/ -------------------------------------------------------------------------------- /samples/minimal-build/automation-solution/tasksRunLocal.tsk: -------------------------------------------------------------------------------- 1 | echo "Minimum function checklist" 2 | VARCHK 3 | 4 | echo "Load a property file to memory" 5 | PROPLD manifest.txt 6 | 7 | echo "Display a resolved variable" 8 | ASSIGN $username = "$var_load" 9 | 10 | echo "Detokenise a setting file" 11 | DETOKN example.yaml 12 | 13 | echo "Detokenise setting file using environment variable" 14 | REPLAC example.yaml @secret@ $HOME 15 | 16 | echo "In a real pipeline, can rely on secret masking" 17 | cat example.yaml 18 | -------------------------------------------------------------------------------- /provisioning/readme.md: -------------------------------------------------------------------------------- 1 | Atomic Provisioning 2 | =================== 3 | The intention of these provisioning scripts is that they are self container with minimal dependancies, i.e. can be executed on a clean OS. 4 | 5 | Interactive Provisioning 6 | ------------------------ 7 | 8 | Role Installers cannot be run via remote powershell without spawning a new window. If running on the local machine and logging capture is desired, set the following environment variable. 9 | 10 | [Environment]::SetEnvironmentVariable('interactive', 'true') -------------------------------------------------------------------------------- /samples/targetlessCD/compose/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | target: 4 | image: "${TARGET_TAG}" 5 | environment: 6 | - MICRO_LISTEN_PORT=${MICRO_LISTEN_PORT} 7 | 8 | test: 9 | image: "${TEST_TAG}" 10 | volumes: 11 | - ${WORK_SPACE}:c:/solution/workspace 12 | depends_on: 13 | - target 14 | 15 | # For binding to existing networks by name, without this a default NAT will be created 16 | #networks: 17 | # default: 18 | # name: nat 19 | # external: true 20 | -------------------------------------------------------------------------------- /samples/custom/automation-solution/tasksRunLocal.tsk: -------------------------------------------------------------------------------- 1 | echo "Minimum function checklist" 2 | VARCHK 3 | 4 | echo "Load a property file to memory`n" 5 | PROPLD manifest.txt 6 | 7 | echo "Display a resolved variable`n" 8 | ASSIGN $username = "$var_load" 9 | 10 | echo "Detokenise a setting file`n" 11 | DETOKN example.yaml 12 | 13 | echo "Detokenise setting file using environment variable`n" 14 | REPLAC example.yaml @secret@ $env:COMPUTERNAME 15 | 16 | echo "In a real pipeline, can rely on secret masking`n" 17 | cat example.yaml 18 | -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/customLocal/Dockerfile: -------------------------------------------------------------------------------- 1 | # DOCKER-VERSION 1.2.0 2 | ARG CONTAINER_IMAGE 3 | FROM ${CONTAINER_IMAGE} 4 | 5 | # Create root, i.e. C:\solution 6 | WORKDIR /solution 7 | 8 | # Shared bootstrap between Docker and Vagrant 9 | COPY bootstrapTarget.ps1 . 10 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"] 11 | RUN ./bootstrapTarget.ps1 12 | 13 | # Change workdir to an new (empty) folder for volume mount to work 14 | WORKDIR /solution/workspace 15 | -------------------------------------------------------------------------------- /samples/targetlessCD/compose/test/Dockerfile: -------------------------------------------------------------------------------- 1 | # DOCKER-VERSION 1.2.0 2 | ARG CONTAINER_IMAGE 3 | FROM ${CONTAINER_IMAGE} 4 | 5 | # Create root, i.e. C:\solution 6 | WORKDIR /solution 7 | 8 | # Place entry script 9 | COPY executeTest.ps1 . 10 | 11 | # Change workdir to an new (empty) folder for volume mount to work 12 | WORKDIR /solution/workspace 13 | 14 | # Unlike the web server, this container is transient, and does not build the wrapper into the image, instead this relies of the volume mount 15 | CMD ["powershell", "-Command", "../executeTest.ps1", "AUTO_TEST"] -------------------------------------------------------------------------------- /orchestration/bamboo-specs/v1/bamboo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | project: 3 | key: YOUREXISTINGPROJECTKEY 4 | plan: 5 | key: NEW 6 | name: The New Key Must be 3 characters 7 | stages: 8 | - jobs: 9 | - scripts: 10 | - "automation\\processor\\buildPackage.bat ${bamboo.buildNumber} ${bamboo.repository.branch.name}" 11 | interpreter: cmd.exe 12 | # requirements: 13 | # - container 14 | artifacts: 15 | - name: Package 16 | path: '*.zip' 17 | - name: TasksLocal 18 | path: 'TasksLocal/**' 19 | -------------------------------------------------------------------------------- /samples/imageBuild/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | solutionName=imagebuild-minimal 2 | artifactPrefix=0.1 3 | 4 | buildImage=cdaf/windows 5 | CDAF_DOCKER_REQUIRED=yes 6 | 7 | # Base Image from Private Registry 8 | # CDAF_PULL_REGISTRY_URL=registry.gitlab.com 9 | # CDAF_PULL_REGISTRY_USER=. 10 | # CDAF_PULL_REGISTRY_TOKEN=$env:GITLAB_REGISTRY_PAT 11 | 12 | # push to registry (exclude URL for DockerHub) 13 | # CDAF_REGISTRY_URL=myregistry.io/repo 14 | # CDAF_REGISTRY_TAG=latest ${CDAF_REGISTRY_URL}/${SOLUTION}:$BUILDNUMBER 15 | # CDAF_REGISTRY_USER=. 16 | # CDAF_REGISTRY_TOKEN=${ACCESS_TOKEN} 17 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/containerDeploy/settings.xml: -------------------------------------------------------------------------------- 1 | 5 | /solution/home/.m2/repository 6 | 7 | 8 | apis 9 | datacom-group 10 | ${ado.pat} 11 | 12 | 13 | -------------------------------------------------------------------------------- /samples/containerDeploy/automation-solution/customRemote/deploy.tsk: -------------------------------------------------------------------------------- 1 | echo "Here we execute the CLI or REST deployment steps, or perhaps execute tests." 2 | echo "Note: the user home is mounted to deployment container." 3 | 4 | echo "`$RELEASE = $RELEASE" 5 | echo "`$OPT_ARG = $OPT_ARG" 6 | echo "`$env:ENVIRONMENT = $env:ENVIRONMENT" 7 | 8 | echo "Download an image" 9 | curl.exe -s -O "$uri" 10 | 11 | echo "Write image to Log" 12 | IMGTXT $filename 13 | 14 | echo "Do not exit as variable not set" 15 | EXITIF $NOT_SET 16 | 17 | echo "`nControlled Exit" 18 | EXITIF $RELEASE Release 19 | 20 | echo "THIS LINE SHOULD NOT EXECUTE" 21 | exit 666 22 | -------------------------------------------------------------------------------- /samples/imageBuild-custom-image/automation-solution/customLocal/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | ARG CONTAINER_IMAGE 3 | FROM ${CONTAINER_IMAGE} 4 | 5 | # Shared bootstrap between Docker and Vagrant 6 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"] 7 | RUN base.ps1 netfx-4.8-devpack 8 | 9 | # If not using the CDAF base image 10 | # RUN curl.exe -fsO "https://raw.githubusercontent.com/cdaf/windows/refs/heads/master/provisioning/base.ps1" 11 | # RUN ./base.ps1 netfx-4.8-devpack 12 | 13 | # Normal containers run a console application, this is just keeps the container from stopping 14 | CMD ["Wait-Event"] 15 | -------------------------------------------------------------------------------- /samples/all/automation-solution/properties.cm: -------------------------------------------------------------------------------- 1 | context target literal zero integer var_load csv list null_var empty_var 2 | local WINDOWS "Hello World" '0' 3 $env:EXAMPLE_SECRET_2 value1,value2,value3 $csv $null '' 3 | local WORKGROUP "Hello World" '0' 4 $env:EXAMPLE_SECRET_2 valueA,valueB,valueC $csv $null '' 4 | remote VAGRANT_CERTIFICATE_DECRYPT "Hello World" '0' 5 $env:EXAMPLE_SECRET_2 valueA,valueB,valueC $csv $null '' 5 | local VAGRANT_LOCAL "Hello World" '0' 6 $env:EXAMPLE_SECRET_2 valueA,valueB,valueC $csv $null '' 6 | -------------------------------------------------------------------------------- /provisioning/trustedHosts.ps1: -------------------------------------------------------------------------------- 1 | 2 | $scriptName = 'trustedHosts.ps1' 3 | Write-Host "`n[$scriptName] ---------- start ----------" 4 | $trustedHosts = $args[0] 5 | 6 | # Output File (plain text or XML depending on method) must be supplioed 7 | if ($trustedHosts) { 8 | Write-Host "[$scriptName] trustedHosts : $trustedHosts" 9 | } else { 10 | Write-Host "[$scriptName] trustedHosts not passed! Exiting"; exit 100 11 | } 12 | 13 | Write-Host "`n[$scriptName] Add the trustedHosts ($trustedHosts) as a trusted hosts for Remote Powershell" 14 | Set-WSManInstance -ResourceURI winrm/config/client -ValueSet @{TrustedHosts=$trustedHosts} 15 | 16 | Write-Host "`n[$scriptName] ---------- stop -----------`n" 17 | exit 0 -------------------------------------------------------------------------------- /samples/crypt/devops/properties.cm: -------------------------------------------------------------------------------- 1 | context target deployHost zero integer dbreaderwriter dbuserpassword remoteUser remotePass 2 | remote VAGRANT windows-1.mshome.net '0' 1 databaseuser $env:USERNAME $env:CDAF_PS_USERNAME $env:CDAF_PS_USERPASS 3 | local VAGRANT $env:COMPUTERNAME '0' 2 databaseuser $env:USERNAME 4 | local WINDOWS $env:COMPUTERNAME '0' 3 databaseuser $env:USERNAME 5 | local WORKGROUP $env:COMPUTERNAME '0' 4 databaseuser $env:USERNAME 6 | local TEST test.mshome.net '0' 5 databaseuser $env:USERNAME 7 | local PROD prod.mshome.net '0' 6 databaseuser $env:USERNAME -------------------------------------------------------------------------------- /samples/imageBuild-custom-image/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | solutionName=imagebuild 2 | artifactPrefix=0.1 3 | 4 | buildImage=docker.io/cdaf/windows:latest 5 | imageBuild=& "$AUTOMATIONROOT/remote/imageBuild.ps1" ${SOLUTION}_${REVISION} ${BUILDNUMBER} ${buildImage} ${LOCAL_WORK_DIR} 6 | CDAF_DOCKER_REQUIRED=yes 7 | 8 | # Base Image from Private Registry 9 | # CDAF_PULL_REGISTRY_URL=registry.gitlab.com 10 | # CDAF_PULL_REGISTRY_USER=. 11 | # CDAF_PULL_REGISTRY_TOKEN=$env:GITLAB_REGISTRY_PAT 12 | 13 | # push to registry (exclude URL for DockerHub) 14 | # CDAF_REGISTRY_URL=myregistry.io/repo 15 | # CDAF_REGISTRY_TAG=${CDAF_REGISTRY_URL}/${SOLUTION}:$BUILDNUMBER 16 | # CDAF_REGISTRY_USER=. 17 | # CDAF_REGISTRY_TOKEN=${ACCESS_TOKEN} 18 | -------------------------------------------------------------------------------- /samples/containerBuild-custom-image/Readme.md: -------------------------------------------------------------------------------- 1 | # Container Build 2 | 3 | This example highlights how a self-hosted build server can use containers to perform isolated builds. This method supports mutually exclusive requirements such as .NET, Java or NodeJS. 4 | 5 | This also enables the developer to codify their build dependencies, via the provisioning script (bootstrapAgent.ps1). 6 | 7 | ## Image Build 8 | 9 | An image is built each time CDAF is run and tagged with build number, the previous version(s) are deleted. 10 | 11 | ## Container Run 12 | 13 | A container is instantiated from the image, with two volume mounts, one for the workspace and another for the user home. The user home mount allows for persisting data between builds, such as Maven cache or dotnet packages. 14 | -------------------------------------------------------------------------------- /provisioning/runner.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo. 3 | echo [%~nx0] ------------------------ 4 | echo [%~nx0] PowerShell Script Runner 5 | echo [%~nx0] ------------------------ 6 | 7 | rem Launcher script that overides execution policy 8 | rem cannot elevate powershell 9 | 10 | set "back=\" 11 | set "command=%cd%%back%%1" 12 | 13 | echo %command% %2 %3 %4 %5 %6 %7 %8 %9 14 | 15 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%command%'" "'%2'" "'%3'" "'%4'" "'%5'" "'%6'" "'%7'" "'%8'" "'%9'" 16 | set result=%errorlevel% 17 | if %result% NEQ 0 ( 18 | echo. 19 | echo [%~nx0] call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command & %command% %2 %3 %4 %5 %6 %7 %8 %9 failed! 20 | echo [%~nx0] Errorlevel = %result% 21 | exit /b %result% 22 | ) 23 | -------------------------------------------------------------------------------- /automation/local/push.ps1: -------------------------------------------------------------------------------- 1 | # The API Key needs to be obtained from the NuGet server to all package push without prompting for credentials 2 | $PACK_LOC = $args[0] 3 | $API_KEY_FILE = $args[1] 4 | $NUGET_URL = $args[2] 5 | 6 | $exitStatus = 0 7 | 8 | $scriptName = $MyInvocation.MyCommand.Name 9 | $userName = [Environment]::UserName 10 | 11 | Write-Host " PACK_LOC = $PACK_LOC" 12 | Write-Host " API_KEY_FILE = $API_KEY_FILE" 13 | Write-Host " NUGET_URL = $NUGET_URL" 14 | 15 | $secure = Get-Content $API_KEY_FILE | ConvertTo-SecureString 16 | $plain = (New-Object System.Management.Automation.PSCredential 'N/A', $secure).GetNetworkCredential().Password 17 | 18 | # Assumes the package location is cleaned and there will be only one eligable 19 | NuGet.exe push $PACK_LOC\*.nupkg -ApiKey $plain -Source $NUGET_URL 20 | -------------------------------------------------------------------------------- /samples/containerBuild-custom-image/Dockerfile: -------------------------------------------------------------------------------- 1 | # escape=` 2 | # Allow override of image as environment variable 3 | ARG CONTAINER_IMAGE=docker.io/cdaf/linux:windows 4 | FROM ${CONTAINER_IMAGE} 5 | 6 | # Create root, i.e. C:\solution 7 | WORKDIR /solution 8 | 9 | # Shared bootstrap between Docker and Vagrant 10 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"] 11 | RUN base.ps1 netfx-4.8-devpack 12 | 13 | # If not using the CDAF base image 14 | # RUN curl.exe -fsO "https://raw.githubusercontent.com/cdaf/windows/refs/heads/master/provisioning/base.ps1" 15 | # RUN ./base.ps1 netfx-4.8-devpack 16 | 17 | # Change workdir to the mapped folder so that the build artefacts are available on the host 18 | WORKDIR /solution/workspace 19 | 20 | CMD ci 21 | -------------------------------------------------------------------------------- /samples/containerDeploy/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Container Deployment 2 | solutionName=container-deploy 3 | artifactPrefix=0.0 4 | 5 | # containerImage used for both containerBuild and containerDeploy if runtimeImage not specified 6 | # containerImage=mcr.microsoft.com/windows/server:ltsc2022 7 | runtimeImage=cdaf/windows 8 | 9 | processSequence=containerTasks.ps1 10 | 11 | # Use non-default image build location, compose/test instead of containerDeploy, note when using a custom directory, this must be included in the storeFor or storeForLocal definition 12 | # containerDeploy=& ${WORK_DIR_DEFAULT}/containerDeploy.ps1 "${TARGET}" "${RELEASE}" "${SOLUTION}" "${BUILDNUMBER}" "${REVISION}" -imageDir compose/test 13 | 14 | # containerDeploy files, can be space separated list 15 | # runtimeFiles=$WORKSPACE_ROOT\release.ps1 16 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/automation-solution/CDAF.solution: -------------------------------------------------------------------------------- 1 | productName=Container Deployment 2 | solutionName=container-deploy 3 | artifactPrefix=0.0 4 | 5 | # containerImage used for both containerBuild and containerDeploy if runtimeImage not specified 6 | # containerImage=mcr.microsoft.com/windows/server:ltsc2022 7 | runtimeImage=cdaf/windows 8 | 9 | processSequence=containerTasks.ps1 10 | 11 | # Use non-default image build location, compose/test instead of containerDeploy, note when using a custom directory, this must be included in the storeFor or storeForLocal definition 12 | # containerDeploy=& ${WORK_DIR_DEFAULT}/containerDeploy.ps1 "${TARGET}" "${RELEASE}" "${SOLUTION}" "${BUILDNUMBER}" "${REVISION}" -imageDir compose/test 13 | 14 | # Include deployable release for feedback loop 15 | runtimeFiles=$WORKSPACE_ROOT\release.ps1 16 | -------------------------------------------------------------------------------- /provisioning/removeFile.ps1: -------------------------------------------------------------------------------- 1 | 2 | $scriptName = 'removeFile.ps1' 3 | Write-Host "`n[$scriptName] Primarily for removing large media files after install" 4 | Write-Host "`n[$scriptName] ---------- start ----------" 5 | $fileToRemove = $args[0] 6 | if ($fileToRemove) { 7 | Write-Host "[$scriptName] fileToRemove : $fileToRemove" 8 | } else { 9 | Write-Host "[$scriptName] fileToRemove not supplied! Exit with `$LASTEXITCODE 1" 10 | exit 1 11 | } 12 | 13 | if ( Test-Path $fileToRemove ) { 14 | write-host "[itemRemove] Delete $fileToRemove" 15 | Remove-Item $fileToRemove -Recurse -Force 16 | if(!$?) { 17 | Write-Host "[$scriptName] DELETE_EXCEPTION Remove-Item $fileToRemove -Recurse -Force" 18 | Write-Host "[$scriptName] Exit with `$LASTEXITCODE 2" 19 | exit 2 20 | } 21 | } 22 | 23 | Write-Host "`n[$scriptName] ---------- stop ----------" 24 | -------------------------------------------------------------------------------- /automation/remote/extract.ps1: -------------------------------------------------------------------------------- 1 | Add-Type -AssemblyName System.IO.Compression.FileSystem 2 | 3 | $packagePath = $args[0] 4 | $packageFile = $args[1] 5 | 6 | $scriptName = "extract.ps1" 7 | 8 | [System.IO.Compression.ZipFile]::ExtractToDirectory("$packagePath\$packageFile.zip", "$packagePath\$packageFile") 9 | $exitcode = $LASTEXITCODE 10 | if ( $exitcode -gt 0 ) { 11 | 12 | Write-Host 13 | Write-Host "[$scriptName (remote)] Package Extraction (Zip) failed with exit code = $exitcode" -ForegroundColor Red 14 | throw "Package Extraction (Zip) failed with exit code = $exitcode" 15 | 16 | } else { 17 | 18 | foreach ($item in (Get-ChildItem -Path $packagePath\$packageFile)) { 19 | Write-Host "[$scriptName (remote)] --> $item" 20 | } 21 | 22 | Write-Host 23 | Write-Host "[$scriptName (remote)] Package Extraction Successful" -ForegroundColor Green 24 | 25 | } 26 | -------------------------------------------------------------------------------- /samples/targetlessCD/readme.md: -------------------------------------------------------------------------------- 1 | # Targetless CD 2 | 3 | > Can only be executed on Windows Server 2022 or Windows 11 4 | 5 | Execute function test without deploying a target, instead, perform test in docker-compose environment. 6 | 7 | This leverages two key featues of imageBuild 8 | 9 | ## Post Build & Package Image Build 10 | 11 | Triggered from the CDAF.solution property 12 | 13 | buildImage=docker.io/library/python:latest 14 | 15 | This launches the default construction process. After the Build and Package is complete, the customer Dockerfile is placed in Taskslocal, this is used to construct the deliverable image. 16 | 17 | ## Build All Images 18 | 19 | At deploy time, the `compose.tsk` calls imageBuild without specifying an image or constructor, this triggers a build of each subdirectory 20 | 21 | ### Default Image 22 | 23 | A base image is not supplied, so `dockerBuild` will attempt to derive from the `runtimeImage` property. 24 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/containerDeploy/Dockerfile: -------------------------------------------------------------------------------- 1 | # DOCKER-VERSION 1.2.0 2 | ARG CONTAINER_IMAGE 3 | FROM ${CONTAINER_IMAGE} 4 | 5 | # Copy solution, provision and then build 6 | WORKDIR /solution 7 | 8 | ENV CDAF_INSTALL_PATH 'c:\cdaf' 9 | 10 | # Provision Build Dependancies, configure Maven cache to use host user profile volume mount 11 | SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'Continue'; $verbosePreference='Continue';"] 12 | COPY bootstrapAgent.ps1 . 13 | RUN .\bootstrapAgent.ps1 anypoint-cli-v4 14 | 15 | COPY properties/* /solution/deploy/ 16 | COPY release.ps1 . 17 | COPY deploy.zip . 18 | RUN powershell -Command Expand-Archive deploy.zip 19 | 20 | # Unlike containerBuild the workspace is not volume mounted, this replicates what the remote deploy process does leaving the image ready to run 21 | WORKDIR /solution/deploy 22 | CMD ["./deploy.ps1", "${ENVIRONMENT}"] 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Continuous Delivery Automation Framework (CDAF) 2 | =============================================== 3 | 4 | License for use and distribution 5 | -------------------------------- 6 | 7 | CDAF is distributed under the GNU LGPL license 8 | 9 | GNU LGPL information 10 | -------------------- 11 | 12 | This library is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU Lesser General Public 14 | License as published by the Free Software Foundation; either 15 | version 2.1 of the License, or (at your option) any later version. 16 | 17 | This library is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | Lesser General Public License for more details. 21 | 22 | You can receive a copy of the GNU Lesser General Public License from 23 | http://www.gnu.org/ 24 | -------------------------------------------------------------------------------- /samples/all/automation-solution/custom/example.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | application: 3 | message: "%literal%" 4 | zero: "%zero%" 5 | integer: "%integer%" 6 | var: "%var_load%" 7 | list_var: "%list%" 8 | list_csv: "%csv%" 9 | empty_var: "%empty_var%" 10 | null_var: "%null_var%" 11 | 12 | ad_hoc_resolved: "@secret@" 13 | 14 | message_resolved: "@literal@" 15 | zero_resolved: "@zero@" 16 | integer_resolved: "@integer@" 17 | var_resolved: "@var_load@" 18 | list_var_resolved: "@list@" 19 | list_csv_resolved: "@csv@" 20 | empty_var_resolved: "@empty_var@" 21 | null_var_resolved: "@null_var@" 22 | 23 | message_revealed: "!literal!" 24 | zero_revealed: "!zero!" 25 | integer_revealed: "!integer!" 26 | var_revealed: "!var_load!" 27 | list_var_revealed: "!list!" 28 | list_csv_revealed: "!csv!" 29 | empty_var_revealed: "!empty_var!" 30 | null_var_revealed: "!null_var!" 31 | -------------------------------------------------------------------------------- /automation/cdEmulate.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cmd /c "exit 0" 3 | 4 | rem Too complicated to derive automation root from Batch runner, so hard coded for windows. 5 | set ACTION=%1 6 | 7 | echo. 8 | echo [%~nx0] -------------------- 9 | echo [%~nx0] Initialise Emulation 10 | echo [%~nx0] -------------------- 11 | 12 | for %%Q in ("%~dp0\.") DO set "AUTOMATIONROOT=%%~fQ" 13 | 14 | rem Launcher script that overides execution policy 15 | rem cannot elevate powershell 16 | 17 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%AUTOMATIONROOT%\processor\cdEmulate.ps1'" "'%ACTION%'" 18 | set result=%errorlevel% 19 | if %result% NEQ 0 ( 20 | echo [%~nx0] ERROR call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command %AUTOMATIONROOT%\processor\cdEmulate.ps1 %ACTION% 21 | echo [%~nx0] Return LASTEXITCODE %result% 22 | echo. 23 | echo [%~nx0] --- End Emulation Error Handling --- 24 | echo. 25 | exit /b %result% 26 | ) 27 | -------------------------------------------------------------------------------- /automation/remote/deploy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo [%~nx0] ExecutionPolicy ByPass ... 3 | 4 | echo. 5 | echo [%~nx0] ------------------------------------ 6 | echo [%~nx0] Remote Execution Policy Override 7 | echo [%~nx0] ------------------------------------ 8 | 9 | rem Launcher script that overides execution policy 10 | rem cannot elevate powershell 11 | 12 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%cd%\%WORK_DIR_DEFAULT%\executeTasks.ps1'" "'%1'" "'%2'" "'%3'" 13 | set result=%errorlevel% 14 | if %result% NEQ 0 ( 15 | echo. 16 | echo [%~nx0] CDAF_DELIVERY_FAILURE call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command %cd%\%WORK_DIR_DEFAULT%\executeTasks.ps1 %1 %2 %3 17 | echo [%~nx0] Return LASTEXITCODE %result% 18 | exit /b %result% 19 | ) 20 | 21 | echo. 22 | echo [%~nx0] ------------------------------------ 23 | echo [%~nx0] Deployment Complete 24 | echo [%~nx0] ------------------------------------ 25 | -------------------------------------------------------------------------------- /automation/remote/push.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo [%0] Push to NuGet URL ... 3 | 4 | set PACKAGE_LOC=%1 5 | set KEY_FILE=%2 6 | set URL=%3 7 | echo. 8 | echo [%~nx0] ------------------ 9 | echo [%~nx0] Local Process 10 | echo [%~nx0] ------------------ 11 | echo [%~nx0] PACKAGE_LOC : %PACKAGE_LOC% 12 | echo [%~nx0] KEY_FILE : %KEY_FILE% 13 | echo [%~nx0] URL : %URL% 14 | 15 | rem Launcher script that overides execution policy 16 | rem cannot elevate powershell 17 | 18 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%cd%\%WORK_DIR_DEFAULT%\automation\local\push.ps1'" "'%PACKAGE_LOC%'" "'%KEY_FILE%'" "'%URL%'" 19 | set result=%errorlevel% 20 | if %result% NEQ 0 ( 21 | echo. 22 | echo [%~nx0] Error %result% returned from ... 23 | echo [%~nx0] call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command %cd%\%WORK_DIR_DEFAULT%\automation\local\push.ps1 %PACKAGE_LOC% %KEY_FILE% %URL% 24 | echo [%~nx0] Errorlevel = %result% 25 | exit /b %result% 26 | ) 27 | -------------------------------------------------------------------------------- /provisioning/EnableFileAndPrintSharing.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "$expression" 5 | try { 6 | Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 11 | } 12 | 13 | $scriptName = 'EnableFileAndPrintSharing.ps1' 14 | Write-Host "`n[$scriptName] ---------- start ----------" 15 | 16 | executeExpression "DISM /Online /Enable-Feature /FeatureName:File-Services /All" 17 | executeExpression "netsh advfirewall firewall set rule group='File and Printer Sharing' new enable=Yes" 18 | 19 | Write-Host "`n[$scriptName] ---------- stop ----------" 20 | exit 0 -------------------------------------------------------------------------------- /orchestration/ado/Multi-stage/templates/azure-pipelines-dockerhub-template.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - deployment: Deploy 3 | displayName: ${{ parameters.displayName }} 4 | environment: ${{ parameters.environment }} 5 | pool: 6 | vmImage: windows-latest 7 | # pool: 8 | # name: Self-hosted Pool Name 9 | strategy: 10 | runOnce: 11 | deploy: 12 | steps: 13 | - task: DownloadBuildArtifacts@0 14 | displayName: Download the build artifacts 15 | inputs: 16 | buildType: current 17 | downloadType: single 18 | artifactName: drop 19 | 20 | - task: PowerShell@2 21 | displayName: CDAF Release Package 22 | env: 23 | DOCKERHUB_TOKEN: $(DOCKERHUB_TOKEN) 24 | inputs: 25 | workingDirectory: $(System.ArtifactsDirectory)/drop 26 | targetType: filePath 27 | filePath: ./release.sh 28 | arguments: ${{ parameters.environment }} 29 | -------------------------------------------------------------------------------- /provisioning/nextFreePort.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [int]$localPort 3 | ) 4 | 5 | $scriptName = 'nextFreePort.ps1' 6 | cmd /c "exit 0" 7 | 8 | # Use the CDAF provisioning helpers 9 | Write-Host "`n[$scriptName] ---------- start ----------" 10 | Write-Host "[$scriptName] localPort : $localPort`n" 11 | 12 | while ($localPort -lt 65535) { 13 | if ( Get-NetUDPEndpoint | Where LocalPort -eq $localPort ) { 14 | Write-Host "[$scriptName] $localPort is use for UDP" 15 | $localPort += 1 16 | } else { 17 | if (Get-NetTCPConnection | Where LocalPort -eq $localPort ) { 18 | Write-Host "[$scriptName] $localPort is use for TCP" 19 | $localPort += 1 20 | } else { 21 | Write-Host "[$scriptName] free port is $localPort" 22 | Write-Host "`n[$scriptName] ---------- finish ----------" 23 | return $localPort 24 | } 25 | Write-Host "[$scriptName] free port is $localPort" 26 | Write-Host "`n[$scriptName] ---------- finish ----------" 27 | return $localPort 28 | } 29 | } 30 | 31 | Write-Host "`n[$scriptName] Failed to find a free port!" 32 | $error.clear() 33 | exit 1 -------------------------------------------------------------------------------- /provisioning/setProductKey.ps1: -------------------------------------------------------------------------------- 1 | $scriptName = 'setProductKey.ps1' 2 | Write-Host 3 | Write-Host "[$scriptName] Install Windows Product key in preparation for activation" 4 | Write-Host 5 | Write-Host "[$scriptName] ---------- start ----------" 6 | $fileFile = $args[0] 7 | if ($fileFile) { 8 | Write-Host "[$scriptName] fileFile : $fileFile" 9 | } else { 10 | $fileFile = "$env:TEMP\productkey.txt" 11 | Write-Host "[$scriptName] fileFile : $fileFile (default)" 12 | } 13 | 14 | Write-Host 15 | if (Test-Path $fileFile ) { 16 | Write-Host "[$scriptName] $fileFile found" 17 | } else { 18 | Write-Host "[$scriptName] $fileFile not found!" 19 | exit 200 20 | } 21 | $key = [IO.File]::ReadAllText($fileFile) 22 | $computer = gc env:computername 23 | $service = get-wmiObject -query "select * from SoftwareLicensingService" -computername $computer 24 | 25 | Write-Host "[$scriptName] Install key and refresh status" 26 | $service.InstallProductKey($key) 27 | $service.RefreshLicenseStatus() 28 | 29 | Write-Host 30 | Write-Host "[$scriptName] ---------- stop -----------" 31 | Write-Host -------------------------------------------------------------------------------- /samples/all/build.tsk: -------------------------------------------------------------------------------- 1 | Write-Host "CDAF Version : $(& $CDAF_CORE/capabilities.ps1 cdaf)" 2 | 3 | Write-Host "Am I an Administrator?`n" -ForegroundColor Magenta 4 | IFADMN "whoami" 5 | 6 | Write-Host "Clean Build workspace (not solution)`n" -ForegroundColor Magenta 7 | REMOVE *.binary 8 | 9 | Write-Host "If ACTION (emulation only) is clean, do not perform any further action`n" -ForegroundColor Magenta 10 | EXITIF $terminate = $ACTION 11 | 12 | Write-Host "artifactPrefix is automatically loaded from CDAF.solution, combine with build number to create symantic (http://semver.org/) version`n" -ForegroundColor Magenta 13 | ASSIGN $symver = "${artifactPrefix}.${BUILDNUMBER}" 14 | 15 | Write-Host "Perform build in DOS Command`n" -ForegroundColor Magenta 16 | EXECMD "echo @echo off > bin.bat" 17 | EXECMD "echo echo Artefact symantic version : $symver >> bin.bat" 18 | .\bin.bat 19 | 20 | Write-Host "Robust URL Check`n" -ForegroundColor Magenta 21 | EXERTY "curl.exe --silent -L -w '%{http_code}' google.com -o NUL" 22 | 23 | Write-Host "Execute outside of WORKSPACE" 24 | cd $TMPDIR 25 | PROPLD $AUTOMATIONROOT\CDAF.windows 26 | -------------------------------------------------------------------------------- /provisioning/setStaticIP.ps1: -------------------------------------------------------------------------------- 1 | $scriptName = 'setStaticIP.ps1' 2 | Write-Host 3 | Write-Host "[$scriptName] ---------- start ----------" 4 | $staticIP = $args[0] 5 | if ($staticIP) { 6 | Write-Host "[$scriptName] staticIP : $staticIP" 7 | } else { 8 | Write-Host "[$scriptName] staticIP not supplied, exiting with exit code 100" 9 | exit 100 10 | } 11 | 12 | foreach ($interface in (Get-DnsClient -InterfaceAlias 'Ethernet*')) { 13 | if ($staticIP -eq (Get-NetIPAddress -InterfaceIndex $interface.InterfaceIndex -AddressFamily 'IPv4').IPAddress ) { 14 | 15 | $PrefixLength = (Get-NetIPAddress -InterfaceIndex $interface.InterfaceIndex -AddressFamily 'IPv4').PrefixLength 16 | $InterfaceIndex = (Get-NetIPAddress -InterfaceIndex $interface.InterfaceIndex -AddressFamily 'IPv4').InterfaceIndex 17 | Set-NetIPAddress -IPAddress $staticIP -PrefixLength $PrefixLength -InterfaceIndex $InterfaceIndex 18 | 19 | # List the setting value 20 | Get-NetIPAddress -InterfaceIndex $interface.InterfaceIndex -AddressFamily 'IPv4' 21 | } 22 | } 23 | 24 | Write-Host 25 | Write-Host "[$scriptName] ---------- stop ----------" 26 | -------------------------------------------------------------------------------- /automation/entry.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cmd /c "exit 0" 3 | 4 | rem This script is for use with Git only and is dependent on "master" branch naming convention 5 | 6 | rem Action can be used to pass staging directory with staging@ prefix or 7 | rem housekeeping with remoteURL@ 8 | 9 | set CDAF_COMMAND_SHELL=yes 10 | 11 | for %%Q in ("%~dp0\.") DO set "AUTOMATIONROOT=%%~fQ" 12 | 13 | echo. 14 | echo [%~nx0] ---------------------------------- 15 | echo [%~nx0] PowerShell Execution Policy ByPass 16 | 17 | rem Launcher script that overides execution policy 18 | rem cannot elevate powershell 19 | 20 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%AUTOMATIONROOT%\entry.ps1'" "'%1'" "'%2'" "'%3'" "'%4'" 21 | set result=%errorlevel% 22 | if %result% NEQ 0 ( 23 | echo [%~nx0] DELIVERY_ERROR call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command %AUTOMATIONROOT%\entry.ps1 %1 %2 %3 %4 24 | echo [%~nx0] Return LASTEXITCODE %result% 25 | exit /b %result% 26 | ) 27 | 28 | echo [%~nx0] PowerShell Policy ByPass Complete 29 | echo [%~nx0] ---------------------------------- 30 | echo. 31 | exit 0 -------------------------------------------------------------------------------- /samples/cd.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$buildNumber, 3 | [string]$branchName 4 | ) 5 | 6 | $scriptName = 'ci.ps1' 7 | cmd /c "exit 0" 8 | 9 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 10 | function executeExpression ($expression) { 11 | $error.clear() 12 | Write-Host "$expression" 13 | try { 14 | $result = Invoke-Expression $expression 15 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 16 | } catch { echo $_.Exception|format-list -force; exit 2 } 17 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 18 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 19 | return $result 20 | } 21 | 22 | 23 | Write-Host "`n[$scriptName] ---------- start ----------`n" 24 | Write-Host "[$scriptName] buildNumber : $buildNumber" 25 | Write-Host "[$scriptName] branchName : $branchName" 26 | 27 | 28 | executeExpression "hostname" 29 | executeExpression "whoami" 30 | 31 | Write-Host "`n[$scriptName] ---------- stop ----------" 32 | $error.clear() 33 | exit 0 -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/customLocal/bootstrapTarget.ps1: -------------------------------------------------------------------------------- 1 | 2 | cmd /c "exit 0" 3 | $scriptName = 'bootstrapTarget.ps1' 4 | 5 | function executeExpression ($expression) { 6 | $error.clear() 7 | Write-Host "$expression" 8 | try { 9 | $output = Invoke-Expression $expression 10 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 11 | } catch { echo $_.Exception|format-list -force; exit 2 } 12 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 13 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 14 | return $output 15 | } 16 | 17 | Write-Host "`n[$scriptName] ---------- start ----------`n" 18 | 19 | Write-Host "[$scriptName] Download latest from GitHub`n" 20 | executeExpression '$env:CDAF_INSTALL_PATH = "c:\cdaf"' 21 | executeExpression '. { iwr -useb https://raw.githubusercontent.com/cdaf/windows/master/install.ps1 } | iex' 22 | 23 | Write-Host "[$scriptName] Add any provisioning needed here`n" 24 | executeExpression "capabilities.ps1" 25 | 26 | Write-Host "`n[$scriptName] ---------- stop ----------" 27 | -------------------------------------------------------------------------------- /orchestration/ado/Multi-stage/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | name: $(Rev:r) 2 | 3 | trigger: 4 | branches: 5 | include: 6 | - '*' 7 | 8 | stages: 9 | - stage: DEV 10 | displayName: CI 11 | # variables: 12 | # - group: Git Reader 13 | jobs: 14 | - template: templates/azure-pipelines-build-template.yml 15 | parameters: 16 | displayName: CI 17 | 18 | - stage: TEST 19 | displayName: User Acceptence Test 20 | condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/master')) 21 | dependsOn: DEV 22 | # variables: 23 | # - group: Test Library Group 24 | jobs: 25 | - template: templates/azure-pipelines-deployment-template.yml 26 | parameters: 27 | displayName: CD 28 | environment: TEST 29 | 30 | - stage: PROD 31 | displayName: Production Gated Deployment 32 | condition: and(succeeded(), eq(variables['build.sourceBranch'], 'refs/heads/master')) 33 | dependsOn: TEST 34 | # variables: 35 | # - group: Production Library Group 36 | jobs: 37 | - template: templates/azure-pipelines-deployment-template.yml 38 | parameters: 39 | displayName: CD 40 | environment: PROD 41 | -------------------------------------------------------------------------------- /automation/processor/delivery.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cmd /c "exit 0" 3 | echo. 4 | echo [%~nx0] ========================================= 5 | echo [%~nx0] Continuous Delivery (CD) Process Starting 6 | echo [%~nx0] ========================================= 7 | 8 | set ENVIRONMENT=%1 9 | set RELEASE=%2 10 | set OPT_ARG=%3 11 | set WORK_DIR_DEFAULT=%4 12 | set SOLUTION=%5 13 | set BUILDNUMBER=%6 14 | 15 | rem Launcher script that overides execution policy 16 | rem cannot elevate powershell 17 | 18 | IF [%WORK_DIR_DEFAULT%] == [] ( 19 | set workDirLocal=TasksLocal 20 | ) ELSE ( 21 | set workDirLocal=%WORK_DIR_DEFAULT% 22 | ) 23 | 24 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%cd%\%workDirLocal%\delivery.ps1'" "'%ENVIRONMENT%'" "'%RELEASE%'" "'%OPT_ARG%'" "'%WORK_DIR_DEFAULT%'" 25 | set result=%errorlevel% 26 | if %result% NEQ 0 ( 27 | echo [%~nx0] CDAF_DELIVERY_FAILURE call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command %cd%\%workDirLocal%\delivery.ps1 %ENVIRONMENT% %RELEASE% %OPT_ARG% %WORK_DIR_DEFAULT% 28 | echo [%~nx0] Return LASTEXITCODE %result% 29 | exit /b %result% 30 | ) 31 | 32 | echo [%~nx0] ========================================= 33 | echo. 34 | exit 0 35 | -------------------------------------------------------------------------------- /automation/ci.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | cmd /c "exit 0" 3 | 4 | rem This script is a simple lauch script 5 | 6 | set BUILDNUMBER=%1 7 | set REVISION=%2 8 | set ACTION=%3 9 | set LOCAL_WORK_DIR=%4 10 | set REMOTE_WORK_DIR=%5 11 | 12 | set CDAF_COMMAND_SHELL=yes 13 | 14 | for %%Q in ("%~dp0\.") do set "AUTOMATIONROOT=%%~fQ" 15 | 16 | echo. 17 | echo [ %~nx0 ] ============================================ 18 | echo [ %~nx0 ] Continuous Integration (CI) Process Starting 19 | echo [ %~nx0 ] ============================================ 20 | 21 | rem Launcher script that overides execution policy 22 | rem cannot elevate powershell 23 | 24 | call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command "& '%AUTOMATIONROOT%\processor\buildPackage.ps1'" "'%BUILDNUMBER%'" "'%REVISION%'" "'%ACTION%'" "'%LOCAL_WORK_DIR%'" "'%REMOTE_WORK_DIR%'" 25 | set result=%errorlevel% 26 | if %result% NEQ 0 ( 27 | echo [%~nx0] BUILD_PACKAGE_ERROR call powershell -NoProfile -NonInteractive -ExecutionPolicy ByPass -command %AUTOMATIONROOT%\processor\buildPackage.ps1 %BUILDNUMBER% %REVISION% %ACTION% %AUTOMATION_ROOT% %LOCAL_WORK_DIR% %REMOTE_WORK_DIR% 28 | echo [%~nx0] Return LASTEXITCODE %result% 29 | exit /b %result% 30 | ) 31 | -------------------------------------------------------------------------------- /orchestration/vagrant-box/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | Vagrant.configure(2) do |config| 9 | config.vm.guest = :windows 10 | config.vm.communicator = "winrm" 11 | config.vm.boot_timeout = 1200 # 20 minutes 12 | config.winrm.timeout = 1800 # 30 minutes 13 | config.winrm.max_tries = 20 14 | config.winrm.retry_limit = 200 # from https://github.com/mitchellh/vagrant/issues/6430 15 | config.winrm.retry_delay = 10 # from https://github.com/mitchellh/vagrant/issues/6430 16 | config.vm.graceful_halt_timeout = 600 17 | #hyper-v: config.vm.provider 'hyperv' do |hyperv, override| 18 | #hyper-v: hyperv.ip_address_timeout = 600 # 10 minutes 19 | #hyper-v: hyperv.auto_start_action = 'Start' 20 | #hyper-v: hyperv.linked_clone = true 21 | #hyper-v: end 22 | #virtbox: config.vm.provider 'virtualbox' do |virtualbox, override| 23 | #virtbox: virtualbox.linked_clone = true 24 | #virtbox: virtualbox.gui = false 25 | #virtbox: end 26 | end 27 | -------------------------------------------------------------------------------- /automation/local/RemoteTest.ps1: -------------------------------------------------------------------------------- 1 | $callingPID = $args[0] 2 | $listPSVer = $args[1] 3 | 4 | $scriptName = 'RemoteTest.ps1' 5 | 6 | Write-Host 7 | Write-Host "[$scriptName] ---------- Start ----------" 8 | Write-Host "[$scriptName] callingPID : $callingPID" 9 | Write-Host "[$scriptName] listPSVer : $listPSVer" 10 | Write-Host "[$scriptName] pwd : $(Get-Location)" 11 | Write-Host "[$scriptName] hostname : $(hostname)" 12 | Write-Host "[$scriptName] whoami : $(whoami)" 13 | Write-Host 14 | if ($listPSVer) { 15 | Write-Host "[$scriptName] PSVersionTable details (`$listPSVer set to $listPSVer):" 16 | $PSVersionTable 17 | } else { 18 | Write-Host "[$scriptName] Computer architecture and Service Pack version (`$listPSVer not set):" 19 | $computer = "." 20 | $sOS =Get-WmiObject -class Win32_OperatingSystem -computername $computer 21 | foreach($sProperty in $sOS) { 22 | write-host " Caption : $($sProperty.Caption)" 23 | write-host " Description : $($sProperty.Description)" 24 | write-host " OSArchitecture : $($sProperty.OSArchitecture)" 25 | write-host " ServicePackMajorVersion : $($sProperty.ServicePackMajorVersion)" 26 | } 27 | } 28 | Write-Host 29 | Write-Host "[$scriptName] ---------- Finish ----------" 30 | Write-Host 31 | -------------------------------------------------------------------------------- /samples/containerBuild-custom-image/automation-solution/bootstrapAgent.ps1: -------------------------------------------------------------------------------- 1 | $scriptName = 'bootstrapAgent.ps1' 2 | 3 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 4 | function executeExpression ($expression) { 5 | $error.clear() 6 | Write-Host "[$scriptName] $expression" 7 | try { 8 | Invoke-Expression $expression 9 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 10 | } catch { echo $_.Exception|format-list -force; exit 2 } 11 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 12 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 13 | } 14 | 15 | cmd /c "exit 0" 16 | # Use the CDAF provisioning helpers 17 | Write-Host "`n[$scriptName] ---------- start ----------`n" 18 | 19 | Write-Host "[$scriptName] Download latest from GitHub`n" 20 | executeExpression '$env:CDAF_INSTALL_PATH = "c:\cdaf"' 21 | executeExpression '. { iwr -useb https://raw.githubusercontent.com/cdaf/windows/master/install.ps1 } | iex' 22 | 23 | Write-Host "[$scriptName] Add any provisioning needed here`n" 24 | executeExpression "capabilities.ps1" 25 | 26 | Write-Host "`n[$scriptName] ---------- stop ----------" 27 | $error.clear() 28 | exit 0 -------------------------------------------------------------------------------- /automation/remote/push.ps1: -------------------------------------------------------------------------------- 1 | function executeExpression ($expression) { 2 | $error.clear() 3 | Write-Host "[$scriptName] $expression" 4 | try { 5 | Invoke-Expression $expression 6 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 7 | } catch { echo $_.Exception|format-list -force; exit 2 } 8 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 9 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 10 | } 11 | 12 | # The API Key needs to be obtained from the NuGet server to all package push without prompting for credentials 13 | $PACK_LOC = $args[0] 14 | $API_KEY_FILE = $args[1] 15 | $NUGET_URL = $args[2] 16 | 17 | $scriptName = 'push.ps1' 18 | 19 | Write-Host "[$scriptName] PACK_LOC : $PACK_LOC" 20 | Write-Host "[$scriptName] API_KEY_FILE : $API_KEY_FILE" 21 | Write-Host "[$scriptName] NUGET_URL : $NUGET_URL" 22 | 23 | $secure = Get-Content $API_KEY_FILE | ConvertTo-SecureString 24 | $plain = (New-Object System.Management.Automation.PSCredential 'N/A', $secure).GetNetworkCredential().Password 25 | 26 | # Assumes the package location is cleaned and there will be only one eligable 27 | executeExpression "NuGet.exe push $PACK_LOC\*.nupkg -ApiKey `$plain -Source $NUGET_URL" 28 | -------------------------------------------------------------------------------- /automation/local/deploy.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$TARGET, 3 | [string]$WORKSPACE, 4 | [string]$warnondeployerror, 5 | [string]$OPT_ARG 6 | ) 7 | 8 | function throwErrorlevel ($trappedExit) { 9 | write-host "[$scriptName] Trapped DOS exit code $trappedExit, throwing as exception`n" -ForegroundColor Red 10 | throw "$trappedExit" 11 | } 12 | 13 | # Dummy script to transition from remote powershell to local power shell via DOS batch execution override 14 | $scriptName = "deploy.ps1" 15 | 16 | write-host "[$scriptName] cd $WORKSPACE" 17 | Set-Location $WORKSPACE 18 | write-host 19 | & .\deploy.bat $TARGET $ENVIRONMENT $OPT_ARG 20 | if ( !$? ) { 21 | $exitCode = $LASTEXITCODE 22 | if ( $exitCode -ne 0 ) { 23 | if ( $warnondeployerror ) { 24 | Write-host "[$scriptName] deploy.bat did not complete normally, however `$warnondeployerror set ($warnondeployerror) so proceeding normally." -ForegroundColor Yellow 25 | cmd /c "exit 0" 26 | & Write-Output "[$scriptName] Reset call operator : ";$? 27 | } else { 28 | throwErrorlevel $exitCode 29 | } 30 | } else { 31 | Write-host "[$scriptName][WARN] `$LASTEXITCODE = $LASTEXITCODE`n `$Error[] = $Error`n" -ForegroundColor Yellow 32 | $Error.clear() 33 | Write-host "[$scriptName] Exit normally ..." -ForegroundColor Yellow 34 | } 35 | } 36 | exit 0 37 | -------------------------------------------------------------------------------- /automation/remote/fixACLs.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$path 3 | ) 4 | $scriptName = 'fixACLs.ps1' 5 | 6 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 7 | function executeExpression ($expression) { 8 | $error.clear() 9 | Write-Host "[$scriptName] $expression" 10 | try { 11 | Invoke-Expression $expression 12 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 13 | } catch { Write-Host $_.Exception|format-list -force; exit 2 } 14 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 15 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 16 | } 17 | 18 | Write-Host "`n[$scriptName] ---------- start ----------" 19 | if ($path) { 20 | Write-Host "[$scriptName] path : $path" 21 | } else { 22 | $path = 'C:\inetpub\wwwroot\' 23 | Write-Host "[$scriptName] path : $path (not passed so set to default)" 24 | } 25 | 26 | if ( ! ( Test-Path $path )) { 27 | Write-Host "`n[$scriptName] Created directory $(mkdir $path)" 28 | } 29 | 30 | Write-Host "`n[$scriptName] `$acl = Get-Acl $path" 31 | $acl = Get-Acl $path 32 | executeExpression "Set-Acl '$path' `$acl" 33 | 34 | Write-Host "`n[$scriptName] --- end ---" 35 | $error.clear() 36 | exit 0 37 | -------------------------------------------------------------------------------- /automation/local/remotePackageManagement.ps1: -------------------------------------------------------------------------------- 1 | $packagePath = $args[0] 2 | $packageFile = $args[1] 3 | 4 | $scriptName = "remotePackageManagement.ps1" 5 | 6 | # If this script has started, then the PowerShell session is valid 7 | Write-Host "[$scriptName (remote)] Connection test Successfull" -ForegroundColor Green 8 | 9 | if ( ! ( Test-Path $packagePath )) { 10 | Write-Host "[$scriptName (remote)] Target path does not exit, create $(New-Item -Path $packagePath -ItemType directory)" 11 | } 12 | 13 | cd $packagePath 14 | $timeStamp = $(get-date -f yyyy-MM-dd-hhmmss) 15 | $packageFileName = $packageFile + ".zip" 16 | 17 | if ( Test-Path $packageFileName ) { 18 | 19 | Write-Host "`n[$scriptName (remote)] Package file ($packageFile.zip) exists rename:" 20 | Write-Host "[$scriptName (remote)] $packageFileName --> $packageFile-$timeStamp.zip" 21 | Move-Item $packageFileName $packageFile-$timeStamp.zip 22 | 23 | } else { 24 | 25 | Write-Host "`n[$scriptName (remote)] Not a re-run, purge landing directory ($(pwd))." 26 | Remove-Item * -Recurse -Force 27 | 28 | } 29 | 30 | if ( Test-Path $packageFile ) { 31 | Write-Host "`n[$scriptName (remote)] Extracted Package directory ($packageFile) exists rename:" 32 | Write-Host "[$scriptName (remote)] $packageFile --> $packageFile-$timeStamp" 33 | Move-Item $packageFile $packageFile-$timeStamp 34 | } 35 | -------------------------------------------------------------------------------- /orchestration/ado/Multi-stage/templates/azure-pipelines-terraform-template.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - deployment: Deploy 3 | displayName: ${{ parameters.displayName }} 4 | environment: ${{ parameters.environment }} 5 | pool: 6 | vmImage: windows-latest 7 | # pool: 8 | # name: Self-hosted Pool Name 9 | 10 | strategy: 11 | runOnce: 12 | deploy: 13 | steps: 14 | - task: DownloadBuildArtifacts@0 15 | displayName: Download the build artifacts 16 | inputs: 17 | buildType: current 18 | downloadType: single 19 | artifactName: drop 20 | 21 | - task: PowerShell@2 22 | displayName: ${{ parameters.environment }} "${{ parameters.action }}" 23 | env: 24 | # Use for deploy (state management) only 25 | TERRAFORM_TOKEN: $(TERRAFORM_TOKEN) 26 | inputs: 27 | workingDirectory: $(System.ArtifactsDirectory)/drop 28 | targetType: 'inline' # Use latest published version 29 | script: | 30 | . { iwr -useb https://cdaf.io/static/app/downloads/cdaf.ps1 } | iex 31 | .\automation\provisioning\base.ps1 terraform 32 | ./release.ps1 ${{ parameters.environment }} $(Build.BuildNumber) "${{ parameters.action }}" 33 | -------------------------------------------------------------------------------- /samples/all/automation-solution/tasksRunRemote.tsk: -------------------------------------------------------------------------------- 1 | Write-Host "CDAF Version : $(& $CDAF_CORE/capabilities.ps1 cdaf)" 2 | 3 | Write-Host "Create a temp directory & copy content to it, then add another file`n" -ForegroundColor Magenta 4 | REFRSH manifest.txt .cdaf-regression-temp-dir 5 | VECOPY example.yaml .cdaf-regression-temp-dir 6 | 7 | Write-Host "Create a zip file from the directory, then extract it to directory with the same name`n" -ForegroundColor Magenta 8 | CMPRSS zipPackage .cdaf-regression-temp-dir 9 | DCMPRS zipPackage 10 | 11 | Write-Host "Remove the temp directory`n" -ForegroundColor Magenta 12 | REMOVE .cdaf-regression-temp-dir 13 | 14 | Write-Host "List host capabilities`n" -ForegroundColor Magenta 15 | & $CDAF_CORE\capabilities.ps1 16 | 17 | Write-Host "Supply by pipeline as an environment variable, see provisioning/encrypt.ps1 to create file`n" -ForegroundColor Magenta 18 | $env:AES_KEY = '29-240-88-121-33-64-150-226-136-160-144-115-127-74-74-30' 19 | 20 | Write-Host "Capture output to file or it will simply be logged and discarded`n" -ForegroundColor Magenta 21 | DECRYP ./crypt/secrets.crypt $env:AES_KEY | Out-File secrets 22 | cat secrets 23 | 24 | Write-Host "Robust URL Check`n" -ForegroundColor Magenta 25 | EXERTY "curl.exe --silent -L -w '%{http_code}' google.com -o NUL" 26 | 27 | Write-Host "Execute outside of WORKSPACE" 28 | cd $TMPDIR 29 | PROPLD $WORKSPACE\manifest.txt 30 | -------------------------------------------------------------------------------- /provisioning/installEXE.ps1: -------------------------------------------------------------------------------- 1 | # Cannot use parameters as opt_arg may contain parameters itself 2 | 3 | $scriptName = 'installEXE.ps1' 4 | 5 | Write-Host "`n[$scriptName] ---------- start ----------" 6 | $exeFile = $args[0] 7 | if ($exeFile) { 8 | Write-Host "[$scriptName] exeFile : $exeFile" 9 | } else { 10 | Write-Host "[$scriptName] Executable file not passed, exiting with code 1";exit 1 11 | } 12 | if (!(Test-Path $exeFile)) { 13 | Write-Host "[$scriptName] $exeFile not found, exiting with code 2";exit 2 14 | } 15 | 16 | $opt_arg = $args[1] 17 | if ($opt_arg) { 18 | Write-Host "[$scriptName] opt_arg : $opt_arg" 19 | } else { 20 | Write-Host "[$scriptName] opt_arg : (not supplied)" 21 | } 22 | 23 | if ($opt_arg) { 24 | Write-Host "`n[$scriptName] `$proc = Start-Process -FilePath `"$exeFile`" -ArgumentList `"$opt_arg`" -PassThru -Wait -NoNewWindow" 25 | $proc = Start-Process -FilePath "$exeFile" -ArgumentList "$opt_arg" -PassThru -Wait -NoNewWindow 26 | } else { 27 | Write-Host "`n[$scriptName] `$proc = Start-Process -FilePath `"$exeFile`" -PassThru -Wait -NoNewWindow" 28 | $proc = Start-Process -FilePath "$exeFile" -PassThru -Wait -NoNewWindow 29 | } 30 | if ( $proc.ExitCode -ne 0 ) { 31 | Write-Host "`n[$scriptName] Exit with `$LASTEXITCODE = $($proc.ExitCode)`n" 32 | exit $proc.ExitCode 33 | } 34 | 35 | Write-Host "`n[$scriptName] ---------- stop ----------" 36 | -------------------------------------------------------------------------------- /provisioning/sqlLocalDBInstance.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "$expression" 5 | try { 6 | Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 11 | } 12 | 13 | $scriptName = 'sqlLocalDBInstance.ps1' 14 | 15 | Write-Host 16 | Write-Host "[$scriptName] ---------- start ----------" 17 | $instanceName = $args[0] 18 | if ($instanceName) { 19 | Write-Host "[$scriptName] instanceName : $instanceName" 20 | } else { 21 | $instanceName = 'MSSQLLocalDB' 22 | Write-Host "[$scriptName] instanceName : $instanceName (not supplied, so default used)" 23 | } 24 | 25 | $exists = SqlLocalDB.exe info | findstr.exe $instanceName 26 | 27 | Write-Host 28 | if ( $exists ) { 29 | executeExpression "SqlLocalDB.exe start $instanceName" 30 | } else { 31 | executeExpression "SqlLocalDB.exe create $instanceName" 32 | executeExpression "SqlLocalDB.exe start $instanceName" 33 | } 34 | 35 | Write-Host 36 | executeExpression "foreach (`$instance in SqlLocalDB.exe info ) { SqlLocalDB.exe info `$instance }" 37 | 38 | Write-Host 39 | Write-Host "[$scriptName] ---------- stop ----------" 40 | -------------------------------------------------------------------------------- /provisioning/applyWindowsUpdates.ps1: -------------------------------------------------------------------------------- 1 | # Only for Windows Server 2016 and above 2 | $scriptName = 'applyWindowsUpdates.ps1' 3 | Write-Host "`n[$scriptName] ---------- start ----------" 4 | $autoRestart = $args[0] 5 | if ($autoRestart) { 6 | Write-Host "[$scriptName] autoRestart : $autoRestart" 7 | } else { 8 | $autoRestart = 'yes' 9 | Write-Host "[$scriptName] autoRestart : $autoRestart (default)" 10 | } 11 | 12 | try { 13 | Write-Host "[$scriptName] Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force" 14 | Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force 15 | 16 | Write-Host "[$scriptName] Set-PSRepository -Name PSGallery -InstallationPolicy Trusted" 17 | Set-PSRepository -Name PSGallery -InstallationPolicy Trusted 18 | 19 | Write-Host "[$scriptName] Install-Module -Name PSWindowsUpdate -Confirm:`$False" 20 | Install-Module -Name PSWindowsUpdate -Confirm:$False 21 | 22 | Write-Host "[$scriptName] Import-Module PSWindowsUpdate" 23 | Import-Module PSWindowsUpdate 24 | 25 | if ($autoRestart -eq 'yes') { 26 | Write-Host "[$scriptName] Get-WUInstall -Verbose -AcceptAll -AutoReboot:`$True -Confirm:`$False" 27 | Get-WUInstall -Verbose -AcceptAll -AutoReboot:$True -Confirm:$False 28 | } else { 29 | Write-Host "[$scriptName] Get-WUInstall -Verbose -AcceptAll -AutoReboot:`$False -Confirm:`$False" 30 | Get-WUInstall -Verbose -AcceptAll -AutoReboot:$False -Confirm:$False 31 | } 32 | 33 | } catch { Write-Host $_.Exception|format-list -force; exit 5 } 34 | 35 | Write-Host "`n[$scriptName] ---------- stop ----------" 36 | -------------------------------------------------------------------------------- /orchestration/jenkins/jenkins-scripted-pipeline/Jenkinsfile: -------------------------------------------------------------------------------- 1 | node { 2 | properties( 3 | [ 4 | [ 5 | $class: 'BuildDiscarderProperty', 6 | strategy: [$class: 'LogRotator', numToKeepStr: '10'] 7 | ], 8 | pipelineTriggers( 9 | [ 10 | [$class: "SCMTrigger", scmpoll_spec: "H/3 * * * *"], 11 | ] 12 | ) 13 | ] 14 | ) 15 | } 16 | 17 | node { 18 | try { 19 | withEnv(["BRANCH_NAME=${env.BRANCH_NAME}"]) { 20 | stage ('Application Build and Test') { 21 | checkout scm 22 | bat "automation\\ci.bat ${BUILD_NUMBER} ${BRANCH_NAME}" 23 | } 24 | } 25 | 26 | if ( env.BRANCH_NAME == 'master' ) { 27 | 28 | stage ('Automated Test') { 29 | bat "TasksLocal\\delivery.bat CD" 30 | } 31 | 32 | stage ('Acceptance Test') { 33 | bat "TasksLocal\\delivery.bat TEST" 34 | } 35 | 36 | stage ('Product Owner Approval') { input "Deploy to Production?" } 37 | 38 | stage ('Production') { 39 | bat "TasksLocal\\delivery.bat PROD" 40 | } 41 | } 42 | } 43 | 44 | catch (e) { 45 | currentBuild.result = "FAILED" 46 | println currentBuild.result 47 | notifyFailed() 48 | throw e 49 | } 50 | 51 | finally { 52 | junit '**/test-results/*.xml' 53 | } 54 | } 55 | 56 | def notifyFailed() { 57 | 58 | emailext ( 59 | recipientProviders: [[$class: 'DevelopersRecipientProvider']], 60 | subject: "Jenkins Job [${env.JOB_NAME}] Build [${env.BUILD_NUMBER}] failure", 61 | body: "Check console output at ${env.BUILD_URL}" 62 | ) 63 | } -------------------------------------------------------------------------------- /provisioning/CredDelegation.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "$expression" 5 | try { 6 | Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 11 | } 12 | 13 | $scriptName = 'CredDelegation.ps1' 14 | Write-Host 15 | Write-Host "Applies Windows Domain : Allow a user or computer to delegate, i.e. `"double hop`"" 16 | Write-Host 17 | Write-Host "[$scriptName] ---------- start ----------" 18 | $identity = $args[0] 19 | if ($identity) { 20 | Write-Host "[$scriptName] identity : $identity" 21 | } else { 22 | $identity = 'deployer' 23 | Write-Host "[$scriptName] identity : $identity (default)" 24 | } 25 | 26 | $entity = $args[1] 27 | if ($entity) { 28 | Write-Host "[$scriptName] entity : $entity (choices user or computer)" 29 | } else { 30 | $entity = 'user' 31 | Write-Host "[$scriptName] entity : $entity (default, choices user or computer)" 32 | } 33 | 34 | if ($entity -eq 'user') { 35 | executeExpression "Set-ADUser -Identity $identity -TrustedForDelegation `$True" 36 | } else { 37 | executeExpression "Set-ADComputer -Identity $passthruHost -TrustedForDelegation `$True" 38 | } 39 | 40 | Write-Host 41 | Write-Host "[$scriptName] ---------- stop ----------" 42 | -------------------------------------------------------------------------------- /orchestration/vagrant-test/Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | # All Vagrant configuration is done below. The "2" in Vagrant.configure 5 | # configures the configuration version (we support older styles for 6 | # backwards compatibility). Please don't change it unless you know what 7 | # you're doing. 8 | 9 | # This file is used by AtlasPackage.ps1 for verifying CDAF base boxes 10 | if ENV['OVERRIDE_IMAGE'] 11 | vagrantBox = ENV['OVERRIDE_IMAGE'] 12 | else 13 | puts "OVERRIDE_IMAGE not specified! Set environment variable and retry" 14 | exit 7724 15 | end 16 | 17 | Vagrant.configure(2) do |config| 18 | 19 | # Build Server, fills the role of the build agent and delivers to the host above 20 | config.vm.define 'test' do |test| 21 | test.vm.box = "#{vagrantBox}" 22 | test.vm.provision 'shell', inline: 'Write-Host "pwd = $(pwd)"' 23 | test.vm.provision 'shell', inline: 'Write-Host "whoami = $(whoami)"' 24 | test.vm.provision 'shell', inline: 'systeminfo' 25 | 26 | # Oracle VirtualBox with private NAT has insecure deployer keys for desktop testing 27 | test.vm.provider 'virtualbox' do |virtualbox, override| 28 | override.vm.network 'private_network', ip: '172.16.17.100' 29 | end 30 | 31 | # Microsoft Hyper-V does not support NAT or setting hostname. vagrant up build --provider hyperv 32 | test.vm.provider 'hyperv' do |hyperv, override| 33 | hyperv.vmname = "windows-test" 34 | if ENV['VAGRANT_SMB_PASS'] 35 | override.vm.synced_folder ".", "/vagrant", type: "smb", smb_username: "#{ENV['VAGRANT_SMB_USER']}", smb_password: "#{ENV['VAGRANT_SMB_PASS']}", mount_options: ["vers=2.1"] 36 | end 37 | end 38 | end 39 | 40 | end -------------------------------------------------------------------------------- /provisioning/encypt.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$inputFile, 3 | [string]$encryptedFile, 4 | [string]$stringKeyIn 5 | ) 6 | 7 | cmd /c "exit 0" 8 | 9 | $scriptName = 'encrypt.ps1' 10 | 11 | Write-Host "`n[$scriptName] Create an encrypted file using AES key " 12 | Write-Host "`n[$scriptName] ---------- start ----------" 13 | if ($inputFile) { 14 | Write-Host "[$scriptName] inputFile : $inputFile" 15 | } else { 16 | Write-Host "[$scriptName] inputFile not suppplied!"; exit 101 17 | } 18 | 19 | if ($encryptedFile) { 20 | Write-Host "[$scriptName] encryptedFile : $encryptedFile" 21 | } else { 22 | $encryptedFile = $inputFile 23 | Write-Host "[$scriptName] encryptedFile : (not suppplied, existing file will be replaced)" 24 | } 25 | 26 | if ($stringKeyIn) { 27 | Write-Host "[$scriptName] stringKeyIn : `$stringKeyIn (example format 29-240-88-121-33-64-150-226-136-160-144-115-127-74-74-30)" 28 | $key = @() 29 | $key = $stringKeyIn.Split('-') 30 | } else { 31 | Write-Host "[$scriptName] stringKeyIn : (not supplied, new key will be generated, example format 29-240-88-121-33-64-150-226-136-160-144-115-127-74-74-30)" 32 | $Key = New-Object Byte[] 16 # You can use 16, 24, or 32 for AES 33 | [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($Key) 34 | $stringKeyOut = "" 35 | foreach ($element in $key) { $stringKeyOut += "-$element" } 36 | $stringKeyOut = $stringKeyOut.Substring(1) 37 | } 38 | 39 | Get-Content $inputFile -Raw | ConvertTo-SecureString -AsPlainText -Force | ConvertFrom-SecureString -key $Key | Out-File $encryptedFile 40 | if ( $stringKeyOut ) { 41 | $stringKeyOut 42 | } 43 | Write-Host "`n[$scriptName] ---------- stop ----------" 44 | -------------------------------------------------------------------------------- /samples/custom/automation-solution/customLocal/customDeploy.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$SOLUTION, 3 | [string]$BUILD, 4 | [string]$ENVIRONMENT 5 | ) 6 | 7 | $Error.Clear() 8 | cmd /c "exit 0" 9 | $scriptName = 'customDeploy.ps1' 10 | 11 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 12 | function executeExpression ($expression) { 13 | Write-Host "[$(Get-Date)] $expression" 14 | try { 15 | Invoke-Expression $expression 16 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; $error ; exit 1111 } 17 | } catch { Write-Output $_.Exception|format-list -force; $error ; exit 1112 } 18 | if ( $LASTEXITCODE ) { 19 | if ( $LASTEXITCODE -ne 0 ) { 20 | Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red ; $error ; exit $LASTEXITCODE 21 | } else { 22 | if ( $error ) { 23 | Write-Host "[$scriptName][WARN] $Error array populated by `$LASTEXITCODE = $LASTEXITCODE, $error[] =`n" -ForegroundColor Yellow 24 | $error 25 | } 26 | } 27 | } else { 28 | if ( $error ) { 29 | Write-Host "[$scriptName][WARN] $Error array populated but LASTEXITCODE not set, $error[] =`n" -ForegroundColor Yellow 30 | $error 31 | } 32 | } 33 | } 34 | 35 | Write-Host "`n[$scriptName] ---------- start ----------" 36 | Write-Host "[$scriptName] SOLUTION : $SOLUTION" 37 | Write-Host "[$scriptName] BUILD : $BUILD" 38 | Write-Host "[$scriptName] ENVIRONMENT : $ENVIRONMENT" 39 | Write-Host "[$scriptName] TARGET : $TARGET" 40 | 41 | & ./Transform.ps1 $TARGET | ForEach-Object { invoke-expression $_ } 42 | 43 | executeExpression "dir" 44 | 45 | Write-Host "`n[$scriptName] ---------- stop ----------" 46 | -------------------------------------------------------------------------------- /provisioning/setWinRM.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "$expression" 5 | try { 6 | Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 11 | } 12 | 13 | 14 | $scriptName = 'setStaticIP.ps1' 15 | Write-Host 16 | Write-Host "[$scriptName] ---------- start ----------" 17 | $URI = $args[0] 18 | if ($URI) { 19 | Write-Host "[$scriptName] URI : $URI" 20 | } else { 21 | Write-Host "[$scriptName] URI not supplied, valid example winrm/config/winrs" 22 | Write-Host "[$scriptName] Exiting with exit code 100" 23 | exit 100 24 | } 25 | 26 | $name = $args[1] 27 | if ($name) { 28 | Write-Host "[$scriptName] name : $name" 29 | } else { 30 | Write-Host "[$scriptName] name not supplied, valid example MaxShellsPerUser" 31 | Write-Host "[$scriptName] Exiting with exit code 101" 32 | exit 101 33 | } 34 | 35 | $value = $args[2] 36 | if ($value) { 37 | Write-Host "[$scriptName] value : $value" 38 | } else { 39 | Write-Host "[$scriptName] value not supplied, valid example 30" 40 | Write-Host "[$scriptName] Exiting with exit code 102" 41 | exit 102 42 | } 43 | 44 | Write-Host 45 | # Build the command in a format that is supported in PowerShell 46 | executeExpression "winrm set $URI `'@{$name=`"$value`"}`'" 47 | 48 | Write-Host 49 | Write-Host "[$scriptName] ---------- stop ----------" 50 | -------------------------------------------------------------------------------- /orchestration/ado/Multi-stage/templates/azure-pipelines-deployment-template.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | # Environment of Virtual Machines, replaces legacy "Deployment Groups" 3 | - deployment: Release # do not use "Deploy" or job will get stuck at "Job is pending..." 4 | displayName: ${{ parameters.displayName }} 5 | environment: 6 | name: ${{ parameters.environment }} 7 | resourceType: VirtualMachine 8 | 9 | # Deploy to agent pool, either Microsoft hosted or Self-hosted 10 | # - deployment: Deploy 11 | # displayName: ${{ parameters.displayName }} 12 | # environment: ${{ parameters.environment }} 13 | # pool: 14 | # vmImage: windows-latest 15 | # pool: 16 | # name: Self-hosted Pool Name 17 | 18 | strategy: 19 | runOnce: 20 | deploy: 21 | steps: 22 | - task: DownloadBuildArtifacts@0 23 | displayName: Download the build artifacts 24 | inputs: 25 | buildType: current 26 | downloadType: single 27 | artifactName: drop 28 | 29 | # - task: PowerShell@2 30 | # displayName: Diag 31 | # inputs: 32 | # workingDirectory: $(System.ArtifactsDirectory)/drop 33 | # targetType: inline 34 | # script: dir ; systeminfo 35 | 36 | - task: PowerShell@2 37 | displayName: CDAF Release Package 38 | # env: 39 | # CONNECTION_STRING: $(CONNECTION_STRING) 40 | # DATABASE_PASSWORD: $(DATABASE_PASSWORD) 41 | inputs: 42 | workingDirectory: $(System.ArtifactsDirectory)/drop 43 | targetType: filePath 44 | filePath: $(System.ArtifactsDirectory)/drop/release.ps1 45 | arguments: ${{ parameters.environment }} 46 | -------------------------------------------------------------------------------- /orchestration/gitlab/.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # If stages is not defined in the .gitlab-ci.yml file, the default pipeline stages are: 2 | #stages: 3 | # - .pre 4 | # - build 5 | # - test 6 | # - deploy 7 | # - .post 8 | 9 | CI: 10 | stage: build 11 | 12 | # To use native container runner with CDAF pre-installed 13 | image: cdaf/windows 14 | script: entry.ps1 ${CI_PIPELINE_IID} ${CI_COMMIT_BRANCH} 15 | 16 | # Self-hosted Runner 17 | # tags: 18 | # - batch 19 | 20 | # Install Edge Version 21 | # script: | 22 | # . { iwr -useb https://raw.githubusercontent.com/cdaf/windows/master/install.ps1 } | iex 23 | # .\automation\entry.ps1 ${CI_PIPELINE_IID} ${CI_COMMIT_BRANCH} 24 | 25 | # Install Latest Version 26 | # script: | 27 | # . { iwr -useb https://cdaf.io/static/app/downloads/cdaf.ps1 } | iex 28 | # .\automation\entry.bat ${CI_PIPELINE_IID} ${CI_COMMIT_BRANCH} 29 | 30 | artifacts: 31 | paths: 32 | - release.ps1 33 | 34 | TEST: 35 | stage: test 36 | tags: 37 | - batch 38 | script: "./release.ps1 ${CI_JOB_NAME} ${CI_PIPELINE_ID}" 39 | environment: "${CI_JOB_STAGE}" 40 | dependencies: 41 | - CI 42 | only: 43 | - master 44 | 45 | PROD: 46 | stage: deploy 47 | tags: 48 | - batch 49 | script: "./release.ps1 ${CI_JOB_NAME} ${CI_PIPELINE_ID}" 50 | environment: "${CI_JOB_STAGE}" 51 | dependencies: 52 | - TEST 53 | only: 54 | - master 55 | when: manual 56 | 57 | # To apply a hard-dependency on the manual gate, use "needs" 58 | #VERIFY: 59 | # stage: publish 60 | # image: cdaf/linux 61 | # script: | 62 | # ./release.sh ${CI_JOB_NAME} ${CI_PIPELINE_ID} 63 | # dependencies: 64 | # - CI 65 | # - PROD 66 | # needs: 67 | # - CI 68 | # - PROD 69 | # only: 70 | # - main 71 | -------------------------------------------------------------------------------- /automation/local/localTasksTarget.ps1: -------------------------------------------------------------------------------- 1 | 2 | function getProp ($propName) { 3 | try { 4 | $propValue=$(& ${CDAF_CORE}\getProperty.ps1 $propertiesFile $propName) 5 | if(!$?){ taskWarning } 6 | } catch { exceptionExit "LOCAL_TASKS_TARGET_getProp" $_ } 7 | 8 | return $propValue 9 | } 10 | 11 | $ENVIRONMENT = $args[0] 12 | $SOLUTION = $args[1] 13 | $BUILD = $args[2] 14 | $TARGET = $args[3] 15 | $OPT_ARG = $args[4] 16 | 17 | $scriptName = $myInvocation.MyCommand.Name 18 | $propertiesFile = "propertiesForLocalTasks\$TARGET" 19 | 20 | write-host 21 | write-host "[$scriptName] propertiesFile : $propertiesFile" 22 | 23 | $scriptOverride = getProp ("deployScriptOverride") 24 | if ($scriptOverride ) { 25 | $taskList = $scriptOverride 26 | write-host "[$scriptName] deployScriptOverride : $scriptOverride" 27 | Write-Host 28 | $expression=".\$scriptOverride $SOLUTION $BUILD $TARGET" 29 | write-host $expression 30 | try { 31 | Invoke-Expression $expression 32 | if(!$?){ taskFailure "LOCAL_OVERRIDESCRIPT_TRAP" } 33 | } catch { exceptionExit "LOCAL_OVERRIDESCRIPT_EXCEPTION" $_ } 34 | 35 | 36 | } else { 37 | 38 | $taskOverride = getProp ("deployTaskOverride") 39 | if ($taskOverride ) { 40 | $taskList = $taskOverride 41 | } else { 42 | $taskList = "tasksRunLocal.tsk" 43 | } 44 | 45 | Write-Host 46 | foreach ( $taskItem in $taskList.Split() ) { 47 | write-host "`n[$scriptName] --- Executing $taskItem ---`n" -ForegroundColor Green 48 | & ${CDAF_CORE}\execute.ps1 $SOLUTION $BUILD $TARGET $taskItem $OPT_ARG 49 | if($LASTEXITCODE -ne 0){ ERRMSG "LOCAL_TASKS_TARGET_EXECUTE_NON_ZERO_EXIT ${CDAF_CORE}\execute.ps1 $SOLUTION $BUILD $TARGET $taskItem" $LASTEXITCODE } 50 | if(!$?){ taskFailure "LOCAL_TASKS_TARGET_EXECUTE_TRAP" } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /automation/badge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | Continuous Delivery Automation Framework 8 | 9 | 18 | 19 | 20 | Page-1 21 | 22 | Sheet.2 23 | 3.0.0 24 | 25 | 3.0.0 26 | 27 | Sheet.4 28 | 29 | 30 | 31 | Sheet.3 32 | cdaf 33 | 34 | cdaf 35 | 36 | 37 | -------------------------------------------------------------------------------- /provisioning/setSPN.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$spn, 3 | [string]$targetAccount 4 | ) 5 | 6 | cmd /c "exit 0" 7 | $Error.Clear() 8 | 9 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 10 | function executeExpression ($expression) { 11 | Write-Host "[$(Get-Date)] $expression" 12 | try { 13 | Invoke-Expression $expression 14 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; $error ; exit 1111 } 15 | } catch { Write-Output $_.Exception|format-list -force; $error ; exit 1112 } 16 | if ( $LASTEXITCODE ) { 17 | if ( $LASTEXITCODE -ne 0 ) { 18 | Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red ; $error ; exit $LASTEXITCODE 19 | } else { 20 | if ( $error ) { 21 | Write-Host "[$scriptName][WARN] $Error array populated by `$LASTEXITCODE = $LASTEXITCODE, $error[] = $error`n" -ForegroundColor Yellow 22 | $error.clear() 23 | } 24 | } 25 | } else { 26 | if ( $error ) { 27 | Write-Host "[$scriptName][WARN] $Error array populated but LASTEXITCODE not set, $error[] = $error`n" -ForegroundColor Yellow 28 | $error.clear() 29 | } 30 | } 31 | } 32 | 33 | $scriptName = 'setSPN.ps1' 34 | Write-Host "`nConfigure SPN for double hop authentication. Perform on Domain Controller." 35 | Write-Host "`n[$scriptName] ---------- start ----------" 36 | if ($spn) { 37 | Write-Host "[$scriptName] spn : $spn" 38 | } else { 39 | $spn = 'MSSQLSvc/DB:1433' 40 | Write-Host "[$scriptName] spn : $spn (default)" 41 | } 42 | 43 | if ($targetAccount) { 44 | Write-Host "[$scriptName] targetAccount : $targetAccount" 45 | } else { 46 | $targetAccount = 'MSHOME\SQLSA' 47 | Write-Host "[$scriptName] targetAccount : $targetAccount (default)" 48 | } 49 | 50 | executeExpression "setspn.exe -a $spn $targetAccount" 51 | 52 | Write-Host "`n[$scriptName] ---------- stop ----------`n" 53 | -------------------------------------------------------------------------------- /automation/local/copy.ps1: -------------------------------------------------------------------------------- 1 | function taskException ($taskName, $exit, $exception) { 2 | write-host "[$scriptName] Caught an exception excuting $taskName :" -ForegroundColor Red 3 | write-host " Exception Type: $($exception.Exception.GetType().FullName)" -ForegroundColor Red 4 | write-host " Exception Message: $($exception.Exception.Message)" -ForegroundColor Red 5 | exit $exit 6 | } 7 | 8 | function getFilename ($FullPathName) { 9 | 10 | $PIECES=$FullPathName.split('\') 11 | $NUMBEROFPIECES=$PIECES.Count 12 | $FILENAME=$PIECES[$NumberOfPieces-1] 13 | $DIRECTORYPATH=$FullPathName.Trim($FILENAME) 14 | return $FILENAME 15 | 16 | } 17 | 18 | $copyFile = $args[0] 19 | $deployLand = $args[1] 20 | $WORK_DIR_DEFAULT = $args[2] 21 | 22 | $fileName = getFilename($copyFile) 23 | 24 | $scriptName = $myInvocation.MyCommand.Name 25 | $deployPath = "$deployLand\$fileName" 26 | 27 | if ( Test-Path $WORK_DIR_DEFAULT\copyLand.ps1 ) { 28 | Remove-Item $WORK_DIR_DEFAULT\copyLand.ps1 -Recurse 29 | if(!$?){ taskWarning "Remove-Item $WORK_DIR_DEFAULT\copyLand.ps1"} 30 | } 31 | 32 | # The copy method loads the file contents into an argument and streams to a remote writer, to get this to work, 33 | # the target location needs to be a literal and cannot be substituted at runtime, to overcome this the script 34 | # file itself is hardcoded with the desired target location. 35 | $templateFile = @(Get-Content "$WORK_DIR_DEFAULT\copyTemplate.ps1") 36 | $outputFile = "$WORK_DIR_DEFAULT\copyLand.ps1" 37 | $stream = [System.IO.StreamWriter] $outputFile 38 | foreach ($line in $templateFile) { 39 | $line = $line -replace "deployLand", $deployPath 40 | $line = $line -replace "copy.ps1", "copyLand.ps1" 41 | $stream.WriteLine($line) 42 | } 43 | $stream.close() 44 | 45 | try { 46 | & $WORK_DIR_DEFAULT\copyLand.ps1 $copyFile 47 | if(!$?){ taskWarning } 48 | } catch { taskException "$copyFile" 2491 $_ } 49 | -------------------------------------------------------------------------------- /provisioning/addProxy.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$proxyURI 3 | ) 4 | 5 | function executeExpression ($expression) { 6 | $error.clear() 7 | Write-Host "$expression" 8 | try { 9 | $output = Invoke-Expression $expression 10 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 11 | } catch { echo $_.Exception|format-list -force; exit 2 } 12 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 13 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 14 | return $output 15 | } 16 | 17 | $scriptName = 'addDISM.ps1' 18 | 19 | Write-Host "`n[$scriptName] ---------- start ----------`n" 20 | if ($proxyURI) { 21 | Write-Host "[$scriptName] proxyURI : $proxyURI" 22 | } else { 23 | Write-Host "[$scriptName] ERROR: proxyURI not passed, halting with LASTEXITCODE=110"; exit 110 24 | } 25 | 26 | if ($DefaultNetworkCredentials) { 27 | Write-Host "[$scriptName] DefaultNetworkCredentials : $DefaultNetworkCredentials" 28 | } else { 29 | $DefaultNetworkCredentials = 'no' 30 | Write-Host "[$scriptName] DefaultNetworkCredentials : $DefaultNetworkCredentials (default)" 31 | } 32 | 33 | executeExpression "Add-Content $PROFILE `"[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('$proxyURI')`"" 34 | 35 | if ($DefaultNetworkCredentials -eq 'yes') { 36 | executeExpression "Add-Content $PROFILE `"[system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials`"" 37 | } 38 | executeExpression "Add-Content $PROFILE `"[system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = `$true`"" 39 | 40 | executeExpression "$PROFILE" 41 | 42 | Write-Host "`n[$scriptName] List the resulting configuration ..." 43 | [system.net.webrequest]::defaultwebproxy 44 | 45 | Write-Host "`n[$scriptName] ---------- stop ----------" 46 | exit 0 -------------------------------------------------------------------------------- /samples/deliveryScript.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$SOLUTION, 3 | [string]$BUILDNUMBER, 4 | [string]$TARGET 5 | ) 6 | 7 | $scriptName = 'deliveryScript.ps1' 8 | cmd /c "exit 0" 9 | 10 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 11 | function executeExpression ($expression) { 12 | $error.clear() 13 | Write-Host "[$scriptName] $expression" 14 | try { 15 | Invoke-Expression $expression 16 | if(!$?) { Write-Host "[$scriptName][CDAF_DELIVERY_FAILURE.failure] `$? = $?"; exit 1 } 17 | } catch { Write-Host "[$scriptName][CDAF_DELIVERY_FAILURE.exception] ..."; echo $_.Exception|format-list -force; exit 2 } 18 | if ( $error[0] ) { Write-Host "[$scriptName][CDAF_DELIVERY_FAILURE.error] `$error[0] = $error"; exit 3 } 19 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName][CDAF_DELIVERY_FAILURE.exit] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 20 | } 21 | 22 | Write-Host "`n[$scriptName] ---------- start ----------" 23 | Write-Host "[$scriptName] SOLUTION : $SOLUTION" 24 | Write-Host "[$scriptName] BUILDNUMBER : $BUILDNUMBER" 25 | Write-Host "[$scriptName] TARGET : $TARGET" 26 | 27 | & ./Transform.ps1 $TARGET | ForEach-Object { invoke-expression $_ } 28 | 29 | if ( Test-Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Server\ServerLevels' ) { 30 | 31 | Write-Host "Compatibility setting`n" 32 | [Console]::OutputEncoding = [System.Text.Encoding]::Default 33 | 34 | Write-Host "Cleanup from previously failed builds`n" 35 | executeExpression "docker-compose down" 36 | executeExpression "docker-compose rm" 37 | 38 | Write-Host "Create Test SQL Server Container`n" 39 | executeExpression "docker-compose up -d" 40 | 41 | } else { 42 | 43 | Write-Host "This operating system is not a server, please ensure SQL Server is running with sa account and password of Passw0rd!`n" 44 | 45 | } 46 | 47 | Write-Host "`n[$scriptName] ---------- stop ----------" 48 | $error.clear() 49 | exit 0 -------------------------------------------------------------------------------- /provisioning/WIF.ps1: -------------------------------------------------------------------------------- 1 | $scriptName = 'WIF.ps1' 2 | $versionChoices = '4' 3 | Write-Host 4 | Write-Host "[$scriptName] --------------------------" 5 | Write-Host "[$scriptName] Windows Identity Framework" 6 | Write-Host "[$scriptName] --------------------------" 7 | $version = $args[0] 8 | if ($version) { 9 | Write-Host "[$scriptName] version : $version" 10 | } else { 11 | $version = '4' 12 | Write-Host "[$scriptName] version : $version (default, choices $versionChoices)" 13 | } 14 | 15 | $mediaDir = $args[1] 16 | if ($mediaDir) { 17 | Write-Host "[$scriptName] mediaDir : $mediaDir" 18 | } else { 19 | $mediaDir = "$env:TEMP" 20 | Write-Host "[$scriptName] mediaDir : $mediaDir (default)" 21 | } 22 | 23 | if (!( Test-Path $mediaDir )) { 24 | Write-Host "[$scriptName] mkdir $mediaDir" 25 | mkdir $mediaDir 26 | } 27 | 28 | Write-Host 29 | 30 | switch ($version) { 31 | '4' { 32 | $file = 'Windows6.1-KB974405-x64.msu' 33 | $uri = 'https://download.microsoft.com/download/D/7/2/D72FD747-69B6-40B7-875B-C2B40A6B2BDD/' + $file 34 | } 35 | default { 36 | Write-Host "[$scriptName] version not supported, choices are $versionChoices" 37 | } 38 | } 39 | 40 | Write-Host 41 | $fullpath = $mediaDir + '\' + $file 42 | if ( Test-Path $fullpath ) { 43 | Write-Host "[$scriptName] $fullpath exists, download not required" 44 | } else { 45 | 46 | $webclient = new-object system.net.webclient 47 | Write-Host "[$scriptName] $webclient.DownloadFile($uri, $fullpath)" 48 | $webclient.DownloadFile($uri, $fullpath) 49 | } 50 | 51 | try { 52 | $argList = @("$fullpath", '/quiet', '/norestart') 53 | Write-Host "[$scriptName] Start-Process -FilePath `'wusa.exe`' -ArgumentList $argList -PassThru -Wait" 54 | $proc = Start-Process -FilePath 'wusa.exe' -ArgumentList $argList -PassThru -Wait 55 | } catch { 56 | Write-Host "[$scriptName] PowerShell Install Exception : $_" -ForegroundColor Red 57 | exit 200 58 | } 59 | 60 | Write-Host 61 | Write-Host "[$scriptName] ---------- stop -----------" 62 | Write-Host -------------------------------------------------------------------------------- /.github/workflows/delivery.yml: -------------------------------------------------------------------------------- 1 | name: CDAF Targetless CD using hosted agent 2 | # This workflow is triggered on pushes to the repository. 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | name: Continuous Integration & Feature Branch Testing 8 | runs-on: windows-latest 9 | steps: 10 | - name: Checkout 11 | uses: actions/checkout@v4 12 | 13 | - name: Fetch all history for all tags and branches 14 | run: | 15 | git config remote.origin.url https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }} 16 | git fetch --prune --unshallow 17 | 18 | - name: CDAF 19 | shell: powershell # pwsh for PowerShell Core 20 | run: | 21 | cd ${env:GITHUB_WORKSPACE} 22 | cp -Recurse ./samples/crypt/devops solution 23 | .\automation\entry.ps1 ${env:GITHUB_RUN_NUMBER} ${env:GITHUB_REF} 24 | 25 | - name: Artifact Retention 26 | uses: actions/upload-artifact@v4 27 | with: 28 | name: deploy 29 | path: release.ps1 30 | 31 | NO_PROP: 32 | name: Verify nothing attempted when unknown Environment supplied 33 | needs: build 34 | runs-on: windows-latest 35 | steps: 36 | - name: Download Artifacts 37 | uses: actions/download-artifact@v4 38 | with: 39 | name: deploy 40 | path: drop 41 | 42 | - name: NO_PROP 43 | shell: powershell # pwsh for PowerShell Core 44 | run: | 45 | cd ${env:GITHUB_WORKSPACE}\drop 46 | .\release.ps1 NO_PROP 47 | 48 | WINDOWS: 49 | name: Decryption Test from Sample 50 | needs: [build, NO_PROP] 51 | runs-on: windows-latest 52 | steps: 53 | - name: Download Artifacts 54 | uses: actions/download-artifact@v4 55 | with: 56 | name: deploy 57 | path: drop 58 | 59 | - name: WINDOWS 60 | shell: powershell # pwsh for PowerShell Core 61 | run: | 62 | cd ${env:GITHUB_WORKSPACE}\drop 63 | .\release.ps1 WINDOWS 64 | -------------------------------------------------------------------------------- /automation/local/copyTemplate.ps1: -------------------------------------------------------------------------------- 1 | # Emulate Linux SCP transferring file via WinRM 2 | 3 | function taskException ($taskName, $exit, $exception) { 4 | write-host "[$scriptName] Caught an exception excuting $taskName :" -ForegroundColor Red 5 | write-host " Exception Type: $($exception.Exception.GetType().FullName)" -ForegroundColor Red 6 | write-host " Exception Message: $($exception.Exception.Message)" -ForegroundColor Red 7 | exit $exit 8 | } 9 | 10 | $srcPath = $args[0] 11 | 12 | $scriptName = $myInvocation.MyCommand.Name 13 | if (-not(Test-Path $srcPath)) { 14 | write-host "`n[$scriptName] Source file not found! Throwing exception : $srcPath`n" -ForegroundColor Red 15 | throw "$srcPath" 16 | } 17 | 18 | Write-Host "`n[$scriptName] Copy $srcPath to 'deployLand'`n" 19 | try { 20 | [System.IO.FileStream]$srcStream = New-Object IO.FileStream $srcPath, Open 21 | [Byte[]]$readBuffer = New-Object Byte[] 1048576 # 1MB 22 | 23 | do { 24 | 25 | # Read from the input file and create a resulting buffer to the exact length of the stream 26 | $streamLength = $srcStream.Read($readBuffer, 0, $readBuffer.Length) 27 | [Byte[]] $buffer = New-Object Byte[] $streamLength 28 | for ($index = 0; $index -lt $streamLength; $index += 1) { 29 | $buffer[$index] = $readBuffer[$index] 30 | } 31 | 32 | # Process each buffer on the target host 33 | Invoke-Command -Session $session ` 34 | -ScriptBlock { 35 | param( 36 | [Byte[]] $inBuffer 37 | ) 38 | 39 | try { 40 | [System.IO.FileStream]$dstStream = New-Object IO.FileStream 'deployLand', Append 41 | $dstStream.Write($inBuffer, 0, $inBuffer.length) 42 | } catch { 43 | taskException "BUFFER_WRITE" 201 $_ 44 | } finally { 45 | $dstStream.Dispose() 46 | $dstStream = $null 47 | } 48 | } ` 49 | -ArgumentList @( ,$buffer ) 50 | 51 | } while ($streamLength -gt 0) 52 | 53 | } catch { 54 | taskException "BUFFER_READ" 200 $_ 55 | } finally { 56 | 57 | $srcStream.Dispose() 58 | $srcStream = $null 59 | 60 | [System.GC]::Collect() 61 | } 62 | -------------------------------------------------------------------------------- /provisioning/SDK.ps1: -------------------------------------------------------------------------------- 1 | $scriptName = 'SDK.ps1' 2 | $versionChoices = '4.5.2' 3 | Write-Host 4 | Write-Host "[$scriptName] ---------- start ----------" 5 | $version = $args[0] 6 | if ($version) { 7 | Write-Host "[$scriptName] version : $version" 8 | } else { 9 | $version = '4.5.2' 10 | Write-Host "[$scriptName] version : $version (default, choices $versionChoices)" 11 | } 12 | 13 | $mediaDir = $args[1] 14 | if ($mediaDir) { 15 | Write-Host "[$scriptName] mediaDir : $mediaDir" 16 | } else { 17 | $mediaDir = "$env:TEMP" 18 | Write-Host "[$scriptName] mediaDir : $mediaDir (default)" 19 | } 20 | 21 | if (!( Test-Path $mediaDir )) { 22 | Write-Host "[$scriptName] mkdir $mediaDir" 23 | mkdir $mediaDir 24 | } 25 | 26 | switch ($version) { 27 | '4.5.2' { 28 | $file = 'NDP452-KB2901951-x86-x64-DevPack.exe' 29 | $uri = 'http://download.microsoft.com/download/4/3/B/43B61315-B2CE-4F5B-9E32-34CCA07B2F0E/' + $file 30 | } 31 | default { 32 | Write-Host "[$scriptName] version not supported, choices are $versionChoices" 33 | } 34 | } 35 | 36 | $installFile = $mediaDir + '\' + $file 37 | Write-Host "[$scriptName] installFile : $installFile" 38 | 39 | $logFile = $installDir = [Environment]::GetEnvironmentVariable('TEMP', 'user') + '\' + $file + '.log' 40 | Write-Host "[$scriptName] logFile : $logFile" 41 | 42 | Write-Host 43 | if ( Test-Path $installFile ) { 44 | Write-Host "[$scriptName] $installFile exists, download not required" 45 | } else { 46 | 47 | $webclient = new-object system.net.webclient 48 | Write-Host "[$scriptName] $webclient.DownloadFile($uri, $installFile)" 49 | $webclient.DownloadFile($uri, $installFile) 50 | } 51 | 52 | Write-Host 53 | $argList = @('/q', '/norestart') 54 | Write-Host "[$scriptName] Start-Process -FilePath $installFile -ArgumentList $argList -PassThru -Wait" 55 | try { 56 | $proc = Start-Process -FilePath $installFile -ArgumentList $argList -PassThru -Wait 57 | } catch { 58 | Write-Host "[$scriptName] $installFile Exception : $_" -ForegroundColor Red 59 | exit 200 60 | } 61 | 62 | Write-Host 63 | Write-Host "[$scriptName] ---------- stop ----------" 64 | -------------------------------------------------------------------------------- /samples/crypt/devops/CDAF.solution: -------------------------------------------------------------------------------- 1 | solutionName=crypt 2 | # productName=Cryptography Solution 3 | 4 | # Custom Diagnostics on error 5 | # CDAF_ERROR_DIAG=foreach ( $item in ( Get-WmiObject Win32_LogicalDisk )) { get-volume -DriveLetter ($item.DeviceID).split(":")[0] } 6 | 7 | # containerBuild minimum configuration, if a Dockerfile is not found, a default file will be used 8 | # containerImage=cdaf/windows 9 | 10 | # containerBuild default process 11 | # containerBuild=& "${AUTOMATIONROOT}\processor\containerBuild.ps1" "$SOLUTION" "$BUILDNUMBER" "$REVISION" "$ACTION" 12 | 13 | artifactPrefix=0.0 14 | # productVersion=0.0.0 15 | # packageFeatures=minimal 16 | # packageMethod=tarball 17 | 18 | # imageBuild minimum configuration, if a Dockerfile is not found, a default file will be created 19 | # buildImage=cdaf/windows 20 | 21 | # imageBuild default process 22 | # imageBuild=& "$CDAF_CORE\imageBuild.ps1" "${SOLUTION}_${REVISION}" "${BUILDNUMBER}" "${buildImage}" "${LOCAL_WORK_DIR}" 23 | # CDAF_DOCKER_REQUIRED=yes 24 | 25 | # imageBuild integrated push to registry 26 | # CDAF_REGISTRY_URL=${env:CI_REGISTRY} 27 | # CDAF_REGISTRY_TAG=latest ${env:CI_REGISTRY}/linux/${env:SOLUTION}:$BUILDNUMBER 28 | # CDAF_REGISTRY_USER=${env:CI_REGISTRY_USER} 29 | # CDAF_REGISTRY_TOKEN=${env:CI_JOB_TOKEN} 30 | 31 | # defaultBranch=master 32 | # defaultEnvironment=DESKTOP 33 | 34 | # gitRemoteURL=https://github.com/cdaf/${SOLUTION}.git 35 | # gitUserNameEnvVar=${env:GIT_USER} 36 | # gitUserPassEnvVar=${env:GIT_PASS} 37 | # gitCustomCleanup=& $AUTOMATIONROOT\buildandpackage\clean.ps1 38 | 39 | # processSequence=localTasks.ps1 remoteTasks.ps1 containerTasks.ps1 40 | 41 | # containerDeploy minimal config, if directory containerDeploy is found, a customer image build will be attempted 42 | # runtimeImage=cdaf/windows 43 | 44 | # containerDeploy default process 45 | # containerDeploy=& "$CDAF_CORE\containerDeploy.ps1" "${TARGET}" "${RELEASE}" "${SOLUTION}" "${BUILDNUMBER}" "${REVISION}" 46 | 47 | # containerDeploy including additional files in image, and retain the resulting image 48 | # runtimeFiles=$WORKSPACE_ROOT\release.ps1 $CDAF_CORE\embed.ps1 49 | # runtimeRetain=yes 50 | -------------------------------------------------------------------------------- /provisioning/setenv.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$variable, 3 | [string]$value, 4 | [string]$target, 5 | [string]$secret 6 | ) 7 | 8 | cmd /c "exit 0" 9 | $scriptName = 'setenv.ps1' 10 | 11 | function mask ($value) { 12 | return (Get-FileHash -InputStream $([IO.MemoryStream]::new([byte[]][char[]]$value)) -Algorithm MD5).Hash 13 | } 14 | 15 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 16 | function executeExpression ($expression) { 17 | $error.clear() 18 | Write-Host "$expression" 19 | try { 20 | Invoke-Expression $expression 21 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 22 | } catch { Write-Output $_.Exception|format-list -force; exit 2 } 23 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 24 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 25 | } 26 | 27 | Write-Host "`n[$scriptName] ---------- start ----------" 28 | if ( $variable ) { 29 | Write-Host "[$scriptName] variable : $variable" 30 | } else { 31 | $mediaDir = "$env:TEMP" 32 | Write-Host "[$scriptName] mediaDir : $mediaDir (default)" 33 | } 34 | 35 | if ( $value ) { 36 | if (( $secret ) -or ( $variable -like '*key*' ) -or ( $variable -like '*secret*' ) -or ( $variable -like '*password*' ) -or ( $variable -like '*pat*' )) { 37 | Write-Host "[$scriptName] value : $(mask $value) (MD5 mask)" 38 | } else { 39 | Write-Host "[$scriptName] value : $value" 40 | } 41 | } else { 42 | Write-Host "[$scriptName] value required, exiting!" 43 | exit 101 44 | } 45 | 46 | if ( $target ) { 47 | Write-Host "[$scriptName] target : $target (choices user or machine)" 48 | } else { 49 | $target = 'user' 50 | Write-Host "[$scriptName] target : $target (default, choices user or machine)" 51 | } 52 | 53 | Write-Host 54 | executeExpression "[Environment]::SetEnvironmentVariable(`'$variable`', `$value, `'$target`')" 55 | executeExpression "`$env:$variable = [Environment]::GetEnvironmentVariable(`'$variable`', `'$target`')" 56 | 57 | Write-Host "`n[$scriptName] ---------- stop -----------`n" -------------------------------------------------------------------------------- /automation/local/embed.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "[$scriptName] $expression" 5 | try { 6 | Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | } 11 | 12 | $scriptName = 'embed.ps1' 13 | Write-Host 14 | Write-Host "[$scriptName] Turn a file into an embedded string" 15 | Write-Host 16 | Write-Host "[$scriptName] ---------- start ----------" 17 | $fileIn = $args[0] 18 | if ($fileIn) { 19 | Write-Host "[$scriptName] fileIn : $fileIn (choices $configChoices)" 20 | } else { 21 | Write-Host "[$scriptName] Input file not supplied, exiting!" 22 | exit 100 23 | } 24 | 25 | $fileOut = $args[1] 26 | if ($fileOut) { 27 | Write-Host "[$scriptName] fileOut : $fileOut" 28 | } else { 29 | $fileOut = 'embedded.ps1' 30 | Write-Host "[$scriptName] fileOut : $fileOut (default)" 31 | } 32 | 33 | Write-Host 34 | Write-Host "[$scriptName] Test input file ($fileIn) exists" 35 | $extension = [System.IO.Path]::GetExtension("$fileIn") 36 | $verificationFile = 'testfile' + $extension 37 | 38 | Write-Host 39 | Write-Host "[$scriptName] Load input file ($fileIn)" 40 | $ByteArray = [System.IO.File]::ReadAllBytes($fileIn) 41 | $EncodedText = [System.Convert]::ToBase64String($ByteArray) 42 | 43 | if (Test-Path $fileOut) { 44 | Write-Host 45 | Write-Host "[$scriptName] Delete Existing $fileOut" 46 | Remove-Item $fileOut 47 | } 48 | 49 | Write-Host 50 | Write-Host "[$scriptName] Create script ($fileOut) which will generated the embedded file" 51 | Add-Content $fileOut "`$EncodedText = `'$EncodedText`'" 52 | Add-Content $fileOut "`$ByteArray = [System.Convert]::FromBase64String(`$EncodedText)" 53 | Add-Content $fileOut "[System.IO.File]::WriteAllBytes(`'$verificationFile`', `$ByteArray)" 54 | 55 | Write-Host 56 | Write-Host "[$scriptName] Execute scipt ($fileOut) to recreate input file as $verificationFile" 57 | executeExpression "./$fileOut" 58 | 59 | Write-Host 60 | Write-Host "[$scriptName] ---------- stop ----------" 61 | -------------------------------------------------------------------------------- /provisioning/IISPoolAccount.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$poolid, 3 | [string]$poolPassword, 4 | [string]$poolName 5 | ) 6 | 7 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 8 | function executeExpression ($expression) { 9 | $error.clear() 10 | Write-Host "$expression" 11 | try { 12 | Invoke-Expression $expression 13 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 14 | } catch { $_.Exception|format-list -force; exit 2 } 15 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 16 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 17 | } 18 | 19 | $scriptName = 'IISPoolAccount.ps1' 20 | 21 | Write-Host 22 | Write-Host "[$scriptName] ---------- start ----------" 23 | if ($poolid) { 24 | Write-Host "[$scriptName] poolid : $poolid" 25 | } else { 26 | Write-Host "[$scriptName] poolid not supplied! Exit with code 100"; exit 100 27 | } 28 | 29 | if ($poolPassword) { 30 | Write-Host "[$scriptName] poolPassword : *********************" 31 | } else { 32 | Write-Host "[$scriptName] poolPassword : not supplied (assuming Managed Service Account)" 33 | } 34 | 35 | if ($poolName) { 36 | Write-Host "[$scriptName] poolName : $poolName" 37 | } else { 38 | $poolName = 'DefaultAppPool' 39 | Write-Host "[$scriptName] poolName : $poolName (default)" 40 | } 41 | 42 | executeExpression 'Import-Module ServerManager' 43 | executeExpression 'Import-Module WebAdministration' 44 | 45 | try { 46 | $appPool = get-item iis:\apppools\$poolName 47 | } catch { 48 | Write-Host "[$scriptName] Sleep to ensure any previous provisioning is complete" 49 | Start-Sleep 5 50 | $appPool = get-item iis:\apppools\$poolName 51 | } 52 | 53 | Write-Host "`n[$scriptName] Set ID for iis:\apppools\$poolName to $poolid" 54 | $appPool.processModel.userName = $poolid 55 | if ($poolPassword) { 56 | $appPool.processModel.password = $poolPassword 57 | } 58 | $appPool.processModel.identityType = 'SpecificUser' 59 | $appPool | Set-Item 60 | $appPool.Stop() 61 | $appPool.Start() 62 | 63 | Write-Host "[$scriptName] IIS Recycled" 64 | 65 | Write-Host "`n[$scriptName] ---------- stop ----------" 66 | -------------------------------------------------------------------------------- /provisioning/agent.ps1: -------------------------------------------------------------------------------- 1 | function exceptionExit { 2 | param ($exitcode) 3 | write-host 4 | $host.SetShouldExit($exitCode) 5 | exit 6 | } 7 | 8 | function taskComplete { param ($taskName) 9 | write-host 10 | write-host "[$scriptName] Remote Task ($taskName) Successfull " -ForegroundColor Green 11 | write-host 12 | } 13 | 14 | $scriptName = 'agent.ps1' 15 | 16 | Write-Host 17 | Write-Host "[$scriptName] Create an encrypted password file (outfile) for the current user and test against address (targethost)" 18 | Write-Host 19 | Write-Host "[$scriptName] ---------- start ----------" 20 | $targetHost = $args[0] 21 | if ($targetHost) { 22 | Write-Host "[$scriptName] Target Host : $targetHost" 23 | } else { 24 | $targetHost = $(hostname) 25 | Write-Host "[$scriptName] Target Host not passed, default to local host ($targetHost)" 26 | } 27 | 28 | $userID = $args[1] 29 | if ($userID) { 30 | Write-Host "[$scriptName] Target User : $userID" 31 | } else { 32 | $userID = $(whoami) 33 | Write-Host "[$scriptName] Target Host not passed, default to current user ($userID)" 34 | } 35 | 36 | $outputFile = $args[2] 37 | if ($outputFile) { 38 | Write-Host "[$scriptName] Output File : $outputFile" 39 | } else { 40 | $outputFile = "$(hostname)-${targetHost}.crypt" 41 | Write-Host "[$scriptName] Output File not passed, default to $outputFile" 42 | } 43 | 44 | Write-Host 45 | Write-Host "[$scriptName] Pipe password into an encrypted file, enter password : " -NoNewline 46 | read-host -assecurestring | convertfrom-securestring | out-file $outputFile 47 | 48 | Write-Host 49 | Write-Host "[$scriptName] Read the password into a variable (don't print the content of this variable)" 50 | $password = get-content $outputFile | convertto-securestring 51 | 52 | Write-Host 53 | Write-Host "[$scriptName] Create a credential object with the user ID and password" 54 | $cred = New-Object System.Management.Automation.PSCredential ($userID, $password ) 55 | Write-Host 56 | try { 57 | Invoke-Command -credential $cred -ComputerName $targetHost { Write-Host "Running as $(whoami) on $(hostname), test successful" } 58 | if(!$?){ exceptionExit 1 } 59 | } catch { exceptionExit 2 } 60 | 61 | Write-Host 62 | Write-Host "[$scriptName] ---------- stop ----------" 63 | -------------------------------------------------------------------------------- /provisioning/computerCertificate.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$certificateName 3 | ) 4 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 5 | function executeExpression ($expression) { 6 | $error.clear() 7 | $LASTEXITCODE = 0 8 | Write-Host "$expression" 9 | try { 10 | $output = Invoke-Expression $expression 11 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 12 | } catch { echo $_.Exception|format-list -force; exit 2 } 13 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 14 | if ( $LASTEXITCODE -ne 0 ) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 15 | return $output 16 | } 17 | 18 | $scriptName = 'computerCertificate.ps1' 19 | Write-Host "`n[$scriptName] ---------- start ----------" 20 | if ($certificateName) { 21 | Write-Host "[$scriptName] certificateName : $certificateName" 22 | } else { 23 | $certificateName = 'localhost' 24 | Write-Host "[$scriptName] certificateName : $certificateName (not passed, set to default)" 25 | } 26 | 27 | foreach ( $certificate in get-childitem "cert:\localmachine\my" ) { 28 | if ($certificate.DnsNameList -eq "$certificateName") { 29 | if ( $certificate.NotAfter -lt (Get-Date) ) { 30 | Write-Host "[$scriptName] Thumbprint found ($returnValue) but expired $($certificate.NotAfter)" 31 | } else { 32 | $count = $count + 1 33 | $returnValue = $certificate.Thumbprint 34 | Write-Host "[$scriptName] Thumbprint found $returnValue" 35 | } 36 | } 37 | } 38 | 39 | if ( $returnValue ) { 40 | if ( $count -gt 1 ) { 41 | Write-Host "`n[$scriptName] Multiple certificates found for $certificateName, returning last = $returnValue" 42 | } else { 43 | Write-Host "`n[$scriptName] $certificateName certificate exists with thumbprint = $returnValue" 44 | } 45 | } else { 46 | $certificate = executeExpression "New-SelfSignedCertificate -certstorelocation cert:\localmachine\my -dnsname $certificateName" 47 | $returnValue = $certificate.Thumbprint 48 | Write-Host "`n[$scriptName] Created self-signed certificate for $certificateName with thumbprint = $returnValue" 49 | } 50 | 51 | Write-Host "`n[$scriptName] ---------- stop ----------" 52 | $error.clear() 53 | return $returnValue 54 | exit 0 -------------------------------------------------------------------------------- /provisioning/sqlAuthMode.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$mode, 3 | [string]$instance 4 | ) 5 | $scriptName = 'sqlAuthMode.ps1' 6 | cmd /c "exit 0" 7 | 8 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 9 | function executeExpression ($expression) { 10 | $error.clear() 11 | Write-Host "$expression" 12 | try { 13 | $output = Invoke-Expression $expression 14 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 15 | } catch { echo $_.Exception|format-list -force; exit 2 } 16 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 17 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 18 | return $output 19 | } 20 | 21 | Write-Host "`n[$scriptName] Because the instance service has to be restarted, this script only supports execution on the SQL host itself" 22 | Write-Host "`n[$scriptName] ---------- start ----------" 23 | if ($mode) { 24 | Write-Host "[$scriptName] mode : $mode" 25 | } else { 26 | $mode = 'Mixed' 27 | Write-Host "[$scriptName] mode : $mode (default)" 28 | } 29 | 30 | if ($instance) { 31 | $sqlinstance = 'MSSQL$' + $instance 32 | Write-Host "[$scriptName] instance : $sqlinstance" 33 | } else { 34 | $sqlinstance = 'MSSQLSERVER' 35 | Write-Host "[$scriptName] instance : $sqlinstance (default)" 36 | } 37 | 38 | # SMO installed as part of Standard, connect to the local default instance 39 | executeExpression '[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")' 40 | if ($instance) { 41 | $srv = executeExpression 'new-Object Microsoft.SqlServer.Management.Smo.Server(".\$instance")' 42 | } else { 43 | $srv = executeExpression 'new-Object Microsoft.SqlServer.Management.Smo.Server(".")' 44 | } 45 | 46 | executeExpression '$srv.Databases | Select name' # Establish connection 47 | 48 | # Change the mode and restart the instance 49 | executeExpression "`$srv.Settings.LoginMode = [Microsoft.SqlServer.Management.SMO.ServerLoginMode]::$mode" 50 | executeExpression '$srv.Alter()' 51 | executeExpression '$srv.Settings.LoginMode' 52 | executeExpression "Restart-Service '$sqlinstance'" 53 | 54 | Write-Host "`n[$scriptName] ---------- stop ----------" 55 | exit 0 -------------------------------------------------------------------------------- /provisioning/addVSTSPackageCred.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$feedName, 3 | [string]$uri, 4 | [string]$feedPass, 5 | [string]$feedUser, 6 | [string]$nugetPath 7 | ) 8 | $scriptName = 'addVSTSPackageCred.ps1' 9 | 10 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 11 | function executeExpression ($expression) { 12 | $error.clear() 13 | Write-Host "$expression" 14 | try { 15 | Invoke-Expression $expression 16 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 17 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 18 | } catch { echo $_.Exception|format-list -force; exit 2 } 19 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 20 | } 21 | 22 | Write-Host "`n[$scriptName] Add VSTS Package Management credentials to allow non interactive authentication for NuGet." 23 | Write-Host "`n[$scriptName] ---------- start ----------" 24 | if ($feedName) { 25 | Write-Host "[$scriptName] feedName : $feedName" 26 | } else { 27 | Write-Host "[$scriptName] feedName is required"; exit 100 28 | } 29 | 30 | if ($uri) { 31 | Write-Host "[$scriptName] uri : $uri" 32 | } else { 33 | Write-Host "[$scriptName] uri is required"; exit 101 34 | } 35 | 36 | if ($feedPass) { 37 | Write-Host "[$scriptName] feedPass : `$feedPass" 38 | } else { 39 | Write-Host "[$scriptName] feedPass is required"; exit 102 40 | } 41 | 42 | if ($feedUser) { 43 | Write-Host "[$scriptName] feedUser : $feedUser" 44 | } else { 45 | $feedUser = 'usingPAT' 46 | Write-Host "[$scriptName] feedUser : $feedUser (default)" 47 | } 48 | 49 | if ($nugetPath) { 50 | Write-Host "[$scriptName] nugetPath : $nugetPath" 51 | } else { 52 | $nugetPath = 'C:/agent/externals/nuget/nuget.exe' 53 | Write-Host "[$scriptName] nugetPath : $nugetPath (default)" 54 | } 55 | 56 | Write-Host "[$scriptName] whoami : $(whoami)" 57 | 58 | Write-Host "`n[$scriptName] Add Source`n" 59 | executeExpression "$nugetPath sources add -name $feedName -Source $uri -username $feedUser -password `$feedPass" 60 | 61 | Write-Host "`n[$scriptName] List resulting sources`n" 62 | executeExpression "$nugetPath sources" 63 | 64 | Write-Host "`n[$scriptName] ---------- stop ----------" 65 | exit 0 66 | -------------------------------------------------------------------------------- /samples/targetlessCD/automation-solution/customLocal/compose.tsk: -------------------------------------------------------------------------------- 1 | Write-Host "`nLoad the branch (REVISION) and container image from the manifest, placed here by package.tsk`n" 2 | PROPLD manifest.txt 3 | 4 | ASSIGN $id = $("${SOLUTION}_${REVISION}").ToLower() 5 | 6 | cd compose 7 | ..\imageBuild.ps1 ${id} ${BUILDNUMBER} ${containerImage} 8 | cd .. 9 | 10 | ASSIGN $env:TARGET_TAG = "${id}_taskslocal" 11 | ASSIGN $env:TEST_TAG = "${id}_test" 12 | & $WORKSPACE\dockerClean.ps1 $env:TARGET_TAG ${BUILDNUMBER} 13 | & $WORKSPACE\dockerClean.ps1 $env:TEST_TAG ${BUILDNUMBER} 14 | 15 | Write-Host "List containers current state`n" 16 | docker ps 17 | 18 | Write-Host "Load desired state to persistent store`n" 19 | ASSIGN $composePersist = "${env:TEMP}\${id}" 20 | MAKDIR $composePersist 21 | cd $composePersist 22 | $env:WORK_SPACE = $(pwd) 23 | 24 | Write-Host "Cleanup from previously test`n" 25 | if ( Test-Path docker-compose.yml ) { EXECMD "docker-compose down --remove-orphans" } 26 | 27 | Write-Host "Load Release to WORK_SPACE ($env:WORK_SPACE)`n" 28 | $parent = Split-Path -parent $WORKSPACE 29 | Write-Host "`nLoad current artefact set from $parent`n" 30 | VECOPY $WORKSPACE\compose\docker-compose.yml $composePersist 31 | REFRSH $parent\TasksLocal $composePersist\TasksLocal 32 | 33 | Write-Host "Set the build number to use`n" 34 | ASSIGN $env:TARGET_TAG = "${env:TARGET_TAG}:${BUILDNUMBER}" 35 | ASSIGN $env:TEST_TAG = "${env:TEST_TAG}:${BUILDNUMBER}" 36 | 37 | Write-Host "Start target [${env:TARGET_TAG}]`n" 38 | EXECMD "docker-compose up -d target" 39 | $containerID = $(docker ps -aq --filter "ancestor=$env:TARGET_TAG") 40 | & $WORKSPACE\dockerLog.ps1 $containerID 'IIS logging started' 41 | 42 | Write-Host "Execute tests [${env:TEST_TAG}] (allow 5 minutes to complete)`n" 43 | EXECMD "docker-compose up -d test" 44 | $containerID = $(docker ps -aq --filter "ancestor=$env:TEST_TAG") 45 | & $WORKSPACE\dockerLog.ps1 $containerID 'Automated Test Execution completed successfully.' 300 46 | 47 | Write-Host "`nTear down if `$env:COMPOSE_KEEP ($env:COMPOSE_KEEP) not set`n" 48 | if ( $env:COMPOSE_KEEP ) { docker inspect -f '{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq) } else { EXECMD "docker-compose down" } 49 | 50 | cd $WORKSPACE 51 | 52 | echo "Clean-up Transient Directory Created by imageBuild.sh" 53 | REMOVE $env:TEMP/${SOLUTION} 54 | -------------------------------------------------------------------------------- /automation/buildandpackage/loadVSenv.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "[$scriptName] $expression" 5 | try { 6 | Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | } 11 | 12 | $scriptName = 'loadVSenv.ps1' 13 | Write-Host "[$scriptName] ---------- start ----------" 14 | Write-Host 15 | $version = $args[0] 16 | if ($version) { 17 | Write-Host "[$scriptName] version : $version" 18 | } else { 19 | $version = '2015' 20 | Write-Host "[$scriptName] version : not supplied, defaulted to $version" 21 | } 22 | 23 | # from http://stackoverflow.com/questions/2124753/how-i-can-use-powershell-with-the-visual-studio-command-prompt 24 | switch ($version) { 25 | 2017 { 26 | pushd "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools" 27 | cmd /c "VsDevCmd.bat&set" | 28 | foreach { 29 | if ($_ -match "=") { 30 | Write-Host "[$scriptName] $_";$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])" 31 | } 32 | } 33 | popd 34 | Write-Host "`nVisual Studio 2017 Command Prompt variables set." -ForegroundColor Yellow 35 | } 36 | 2015 { 37 | pushd 'C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools' 38 | cmd /c "vsvars32.bat&set" | 39 | foreach { 40 | if ($_ -match "=") { 41 | Write-Host "[$scriptName] $_";$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])" 42 | } 43 | } 44 | popd 45 | write-host "`nVisual Studio 2015 Command Prompt variables set." -ForegroundColor Yellow 46 | } 47 | default { 48 | pushd 'c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC' 49 | cmd /c "vcvarsall.bat&set" | 50 | foreach { 51 | if ($_ -match "=") { 52 | Write-Host "[$scriptName] $_";$v = $_.split("="); set-item -force -path "ENV:\$($v[0])" -value "$($v[1])" 53 | } 54 | } 55 | popd 56 | write-host "`nVisual Studio 2010 Command Prompt variables set." -ForegroundColor Yellow 57 | } 58 | } 59 | 60 | Write-Host 61 | Write-Host "[$scriptName] ---------- stop ----------" 62 | -------------------------------------------------------------------------------- /provisioning/removeUser.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$userName 3 | ) 4 | 5 | cmd /c "exit 0" 6 | $Error.Clear() 7 | 8 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 9 | function executeExpression ($expression) { 10 | Write-Host "[$(Get-Date)] $expression" 11 | try { 12 | Invoke-Expression $expression 13 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; $error ; exit 1111 } 14 | } catch { Write-Output $_.Exception|format-list -force; $error ; exit 1112 } 15 | if ( $LASTEXITCODE ) { 16 | if ( $LASTEXITCODE -ne 0 ) { 17 | Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red ; $error ; exit $LASTEXITCODE 18 | } else { 19 | if ( $error ) { 20 | Write-Host "[$scriptName][WARN] $Error array populated by `$LASTEXITCODE = $LASTEXITCODE, $error[] = $error`n" -ForegroundColor Yellow 21 | $error.clear() 22 | } 23 | } 24 | } else { 25 | if ( $error ) { 26 | Write-Host "[$scriptName][WARN] $Error array populated but LASTEXITCODE not set, $error[] = $error`n" -ForegroundColor Yellow 27 | $error.clear() 28 | } 29 | } 30 | } 31 | 32 | function removeLocal ($userName) { 33 | Write-Host "`n[$scriptName] Workgroup Host, delete local user ($userName).`n" 34 | $ADSIComp = executeExpression "[ADSI]`"WinNT://$Env:COMPUTERNAME,Computer`"" 35 | executeExpression "`$ADSIComp.Delete('User', `"$userName`")" 36 | executeExpression "net user" 37 | } 38 | 39 | $scriptName = 'removeUser.ps1' 40 | Write-Host "`n[$scriptName] Remove User from Domain or Workgroup, Windows Server 2012 and above. Pass .\ prefix for local user.`n" 41 | Write-Host "`n[$scriptName] ---------- start ----------" 42 | if ($userName) { 43 | Write-Host "[$scriptName] userName : $userName" 44 | } else { 45 | $userName = 'vagrant' 46 | Write-Host "[$scriptName] userName : $userName (default)" 47 | } 48 | 49 | if ( $userName.StartsWith('.\')) { 50 | 51 | $prefix, $userName = $userName.Split('\') 52 | removeLocal $userName 53 | 54 | } else { 55 | 56 | if ((gwmi win32_computersystem).partofdomain -eq $true) { 57 | 58 | Write-Host "`n[$scriptName] Remove the new user`n" 59 | executeExpression "Remove-ADUser -Name $userName" 60 | 61 | } else { 62 | 63 | removeLocal $userName 64 | 65 | } 66 | } 67 | 68 | Write-Host "`n[$scriptName] ---------- stop ----------`n" 69 | exit 0 -------------------------------------------------------------------------------- /provisioning/mkdir.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$directoryName, 3 | [string]$userName 4 | ) 5 | 6 | cmd /c "exit 0" 7 | $Error.Clear() 8 | $scriptName = 'mkdir.ps1' 9 | 10 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 11 | function executeExpression ($expression) { 12 | $error.clear() 13 | Write-Host "$expression" 14 | try { 15 | $output = Invoke-Expression $expression 16 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 10 } 17 | } catch { echo $_.Exception|format-list -force; exit 11 } 18 | if ( $error[0] ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 12 } 19 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 20 | return $output 21 | } 22 | 23 | function setACL ($objectName, $userName) { 24 | Write-Host "[$scriptName] List ACL before changes" 25 | Get-Acl $objectName | Format-List 26 | $acl = Get-Acl $objectName 27 | $permission = $userName,"FullControl","Allow" 28 | $accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule $permission 29 | $acl.SetAccessRule($accessRule) 30 | $acl | Set-Acl $objectName 31 | Write-Host "[$scriptName] List ACL after changes" 32 | Get-Acl $objectName | Format-List 33 | } 34 | 35 | Write-Host "`n[$scriptName] ---------- start ----------" 36 | if ($directoryName) { 37 | Write-Host "[$scriptName] directoryName : $directoryName" 38 | } else { 39 | Write-Host "[$scriptName] directoryName not supplied, exiting!" 40 | exit 100 41 | } 42 | 43 | if ($userName) { 44 | Write-Host "[$scriptName] userName : $userName" 45 | } else { 46 | Write-Host "[$scriptName] userName : (not supplied, ACL changes will not be attempted)" 47 | } 48 | 49 | if ( Test-Path $directoryName ) { 50 | Write-Host "[$scriptName] Directory $directoryName already exists, no action attempted." 51 | } else { 52 | executeExpression "New-Item -ItemType Directory -Force -Path `'$directoryName`'" 53 | } 54 | $newDir = executeExpression "New-Item -ItemType Directory -Force -Path `'$directoryName`'" 55 | Write-Host "Created $($newDir.FullName)" 56 | 57 | if ($userName) { 58 | Write-Host 59 | foreach ($item in Get-ChildItem -Recurse $directoryName) { 60 | setACL $item.FullName $userName 61 | } 62 | } 63 | 64 | Write-Host "`n[$scriptName] ---------- stop -----------" 65 | -------------------------------------------------------------------------------- /samples/crypt/devops/tasksRun.tsk: -------------------------------------------------------------------------------- 1 | echo "Some basic functions" 2 | REFRSH . $TMPDIR/workspacecopy 3 | REMOVE TMPDIR/workspacecopy 4 | 5 | Write-Host "Resolve and reveal property, then assign to a named variable`n" -ForegroundColor Green 6 | ASSIGN $HOSTNAME = $deployHost 7 | 8 | Write-Host "Load Propertes as variables and reveal their values`n" -ForegroundColor Green 9 | PROPLD $TARGET reveal 10 | 11 | Write-Host "The following is an example of secrets management" -ForegroundColor Green 12 | Write-Host "DO NOT log the AES key, this is supplied by CD tool as environment variable`n" -ForegroundColor Yellow 13 | $env:AES_KEY = '29-240-88-121-33-64-150-226-136-160-144-115-127-74-74-30' 14 | 15 | Write-Host "A sensitive value can be logged using non-reversable mask" -ForegroundColor Green 16 | $env:AES_KEY_MASK = (MASKED $env:AES_KEY) 17 | 18 | VARCHK properties.varchk 19 | 20 | Write-Host "DO NOT Decrypt without capturing return value or secrets will be disclosed`n" -ForegroundColor Yellow 21 | DECRYP .\crypt\AES_CRYPT $env:AES_KEY 22 | 23 | Write-Host "Either capture Decrypt output to a variable`n" -ForegroundColor Cyan 24 | $secrets = DECRYP .\crypt\AES_CRYPT $env:AES_KEY 25 | 26 | Write-Host "Or stream Decrypt function to reconstruct an encrypted file`n" -ForegroundColor Cyan 27 | DECRYP .\crypt\AES_CRYPT $env:AES_KEY > unencypted.txt 28 | 29 | Write-Host "List content of tokenised properties file`n" -ForegroundColor Green 30 | cat crypt-test.yml 31 | 32 | Write-Host "Detokenise plain text with embedded variable`n" -ForegroundColor Cyan 33 | DETOKN crypt-test.yml $TARGET reveal 34 | 35 | Write-Host "Safe to list as no sensitive values have been transformed`n" -ForegroundColor Green 36 | cat crypt-test.yml 37 | 38 | Write-Host "Detokenise secrets with embedded variable, using non-default token, i.e. @remoteUser@`n" -ForegroundColor Cyan 39 | $env:CDAF_OVERRIDE_TOKEN = '@' 40 | DETOKN crypt-test.yml $TARGET resolve 41 | 42 | Write-Host "If resolved secrets are known CD tool, listing should result in masked values`n" -ForegroundColor Yellow 43 | cat crypt-test.yml 44 | 45 | Write-Host "Detokenise with masked secrets, only supports encrypted name/value files, in-memory, i.e. unencrypted file is never on disk`n" -ForegroundColor Cyan 46 | ASSIGN $env:CDAF_OVERRIDE_TOKEN 47 | DETOKN crypt-test.yml .\crypt\AES_CRYPT $env:AES_KEY 48 | 49 | Write-Host "DO NOT list the contents of the AES detokenised file because CD tool does not know to mask these values`n" -ForegroundColor Red 50 | cat crypt-test.yml -------------------------------------------------------------------------------- /orchestration/jenkins/jenkins-declaritive-pipeline/Jenkinsfile: -------------------------------------------------------------------------------- 1 | pipeline { 2 | agent none 3 | options { 4 | buildDiscarder(logRotator(numToKeepStr: '10')) 5 | } 6 | triggers { 7 | pollSCM 'H/3 * * * *' 8 | } 9 | stages { 10 | stage('Application Build and Test') { 11 | agent any 12 | steps { 13 | checkout scm 14 | bat "automation\\ci.bat ${BUILD_NUMBER} ${BRANCH_NAME}" 15 | } 16 | } 17 | stage('Packer Image') { 18 | when { branch 'master'} 19 | agent any 20 | steps { 21 | sh "TasksLocal/delivery.sh PACKER" 22 | } 23 | } 24 | stage('CD') { 25 | when { branch 'master'} 26 | agent any 27 | steps { 28 | bat "TasksLocal\\delivery.bat ${env.STAGE_NAME}" 29 | } 30 | } 31 | 32 | stage ('Test Manager Approval') { 33 | when { branch 'master'} 34 | steps { 35 | timeout(time:1, unit:'DAYS') { 36 | input message:'Deploy to Acceptence Test?' 37 | } 38 | } 39 | } 40 | 41 | stage('TEST') { 42 | when { branch 'master'} 43 | agent any 44 | steps { 45 | bat "TasksLocal\\delivery.bat ${env.STAGE_NAME}" 46 | } 47 | } 48 | 49 | stage ('Product Owner Approval') { 50 | when { branch 'master'} 51 | steps { 52 | timeout(time:2, unit:'DAYS') { 53 | input message:'Deploy to Production?' 54 | } 55 | } 56 | } 57 | 58 | stage('PROD') { 59 | when { branch 'master'} 60 | agent any 61 | steps { 62 | bat "TasksLocal\\delivery.bat ${env.STAGE_NAME}" 63 | } 64 | } 65 | } 66 | post { 67 | success { 68 | echo 'I succeeeded!' 69 | } 70 | unstable { 71 | echo 'I am unstable :/' 72 | emailext ( 73 | subject: "Jenkins Job Unstable : Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'", 74 | body: "${env.BUILD_URL}", 75 | compressLog: true, 76 | recipientProviders: [[$class: 'DevelopersRecipientProvider']] 77 | ) 78 | } 79 | failure { 80 | echo 'I failed :(' 81 | emailext ( 82 | subject: "Jenkins Job Failed : Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'", 83 | body: "${env.BUILD_URL}", 84 | attachLog: true, 85 | recipientProviders: [[$class: 'DevelopersRecipientProvider']] 86 | ) 87 | } 88 | changed { 89 | echo 'Things were different before...' 90 | } 91 | always { 92 | junit '**/target/surefire-reports/*.xml' 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /provisioning/addFeature.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$feature, 3 | [string]$options, 4 | [string]$media, 5 | [string]$wimIndex 6 | ) 7 | $scriptName = 'addFeature.ps1' 8 | 9 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 10 | function executeExpression ($expression) { 11 | $error.clear() 12 | Write-Host "$expression" 13 | try { 14 | Invoke-Expression $expression 15 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 16 | } catch { echo $_.Exception|format-list -force; exit 2 } 17 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 18 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 19 | } 20 | 21 | Write-Host "`n[$scriptName] Add Windows Feature using DIM source if provided." 22 | Write-Host "`n[$scriptName] ---------- start ----------" 23 | if ($feature) { 24 | Write-Host "[$scriptName] feature : $feature" 25 | } else { 26 | $feature = 'Web-Scripting-Tools' 27 | Write-Host "[$scriptName] feature : $feature (default)" 28 | } 29 | 30 | if ($options) { 31 | Write-Host "[$scriptName] options : $options" 32 | } else { 33 | Write-Host "[$scriptName] options : not supplied" 34 | } 35 | 36 | if ($media) { 37 | Write-Host "[$scriptName] media : $media" 38 | } else { 39 | $media = "$env:TEMP\install.wim" 40 | Write-Host "[$scriptName] media : $media (default)" 41 | } 42 | 43 | if ($wimIndex) { 44 | Write-Host "[$scriptName] wimIndex : $wimIndex" 45 | } else { 46 | $wimIndex = '2' 47 | Write-Host "[$scriptName] wimIndex : $wimIndex (default, Standard Edition)" 48 | } 49 | 50 | # If media is not found, install will attempt to download from windows update 51 | if ( Test-Path $media ) { 52 | if ( $media -match ':' ) { 53 | $sourceOption = '-Source wim:' + $media + ":$wimIndex" 54 | Write-Host "[$scriptName] Media path found, using source option $sourceOption" 55 | } else { 56 | $sourceOption = '-Source ' + $media 57 | Write-Host "[$scriptName] Media path found, using source option $sourceOption" 58 | } 59 | } else { 60 | Write-Host "[$scriptName] media path not found, will attempt to download from windows update." 61 | } 62 | 63 | Write-Host "`n[$scriptName] Install $feature" 64 | executeExpression "Install-WindowsFeature -Name `'$feature`' $options $sourceOption" 65 | 66 | Write-Host "`n[$scriptName] ---------- stop ----------" 67 | exit 0 68 | -------------------------------------------------------------------------------- /provisioning/WIFSDK.ps1: -------------------------------------------------------------------------------- 1 | $scriptName = 'WIFSDK.ps1' 2 | $versionChoices = '4' 3 | Write-Host 4 | Write-Host "[$scriptName] Windows Identity Framework Software Development Kit" 5 | Write-Host 6 | Write-Host "[$scriptName] ---------- start ----------" 7 | $version = $args[0] 8 | if ($version) { 9 | Write-Host "[$scriptName] version : $version" 10 | } else { 11 | $version = '4' 12 | Write-Host "[$scriptName] version : $version (default, choices $versionChoices)" 13 | } 14 | 15 | $mediaDir = $args[1] 16 | if ($mediaDir) { 17 | Write-Host "[$scriptName] mediaDir : $mediaDir" 18 | } else { 19 | $mediaDir = "$env:TEMP" 20 | Write-Host "[$scriptName] mediaDir : $mediaDir (default)" 21 | } 22 | 23 | if (!( Test-Path $mediaDir )) { 24 | Write-Host "[$scriptName] mkdir $mediaDir" 25 | mkdir $mediaDir 26 | } 27 | 28 | Write-Host 29 | 30 | switch ($version) { 31 | '4' { 32 | $file = 'WindowsIdentityFoundation-SDK-4.0.msi' 33 | $uri = 'https://download.microsoft.com/download/7/0/1/70118832-3749-4C75-B860-456FC0712870/' + $file 34 | } 35 | '3.5' { 36 | $file = 'WindowsIdentityFoundation-SDK-3.5.msi' 37 | $uri = 'https://download.microsoft.com/download/7/0/1/70118832-3749-4C75-B860-456FC0712870/' + $file 38 | } 39 | default { 40 | Write-Host "[$scriptName] version not supported, choices are $versionChoices" 41 | } 42 | } 43 | 44 | $installFile = $mediaDir + '\' + $file 45 | Write-Host "[$scriptName] installFile : $installFile" 46 | 47 | $logFile = $installDir = [Environment]::GetEnvironmentVariable('TEMP', 'user') + '\' + $file + '.log' 48 | Write-Host "[$scriptName] logFile : $logFile" 49 | 50 | Write-Host 51 | $fullpath = $mediaDir + '\' + $file 52 | if ( Test-Path $fullpath ) { 53 | Write-Host "[$scriptName] $fullpath exists, download not required" 54 | } else { 55 | $webclient = new-object system.net.webclient 56 | Write-Host "[$scriptName] $webclient.DownloadFile($uri, $fullpath)" 57 | $webclient.DownloadFile($uri, $fullpath) 58 | } 59 | 60 | $argList = @( 61 | "/qn", 62 | "/l*", 63 | "$logFile", 64 | "/i", 65 | "$installFile" 66 | ) 67 | 68 | Write-Host "[$scriptName] Start-Process -FilePath msiexec -ArgumentList $argList -PassThru -Wait" 69 | try { 70 | $proc = Start-Process -FilePath msiexec -ArgumentList $argList -PassThru -Wait 71 | } catch { 72 | Write-Host "[$scriptName] $media Install Exception : $_" -ForegroundColor Red 73 | exit 200 74 | } 75 | 76 | Write-Host 77 | Write-Host "[$scriptName] ---------- stop -----------" 78 | Write-Host -------------------------------------------------------------------------------- /orchestration/bitbucket/bitbucket-pipelines.yml: -------------------------------------------------------------------------------- 1 | pipelines: 2 | default: 3 | - step: 4 | name: Build and test 5 | runs-on: 6 | - windows 7 | 8 | # Custom tags must be ADDITIONAL to the inbuild tags 9 | # - docker.2019 10 | 11 | script: 12 | 13 | # Using CDAF Edge 14 | # - . { iwr -useb https://raw.githubusercontent.com/cdaf/windows/master/install.ps1 } | iex 15 | 16 | # Use Latest Stable 17 | - . { iwr -useb https://cdaf.io/static/app/downloads/cdaf.ps1 } | iex 18 | 19 | - $env:DOCKER_HOST = '' 20 | - .\automation\entry.ps1 $env:BITBUCKET_BUILD_NUMBER $env:BITBUCKET_BRANCH 21 | 22 | branches: 23 | 'master': 24 | - step: 25 | name: Build and test 26 | runs-on: 27 | - windows 28 | script: 29 | - . { iwr -useb https://cdaf.io/static/app/downloads/cdaf.ps1 } | iex 30 | - $env:DOCKER_HOST = '' 31 | - .\automation\ci.bat $env:BITBUCKET_BUILD_NUMBER $env:BITBUCKET_BRANCH 32 | artifacts: 33 | - "release.ps1" 34 | 35 | # Legacy artefacts 36 | # artifacts: 37 | # - "TasksLocal/**" 38 | # - "*.zip" 39 | 40 | - step: 41 | name: Deploy to test 42 | runs-on: 43 | - windows 44 | deployment: Test 45 | script: 46 | - $env:DOCKER_HOST = '' 47 | - ./release.ps1 $env:BITBUCKET_DEPLOYMENT_ENVIRONMENT 48 | 49 | # Legacy Delivery 50 | # - ./TasksLocal/delivery.ps1 $env:BITBUCKET_DEPLOYMENT_ENVIRONMENT 51 | 52 | - step: 53 | name: Deploy to staging 54 | deployment: Staging 55 | script: 56 | - $env:DOCKER_HOST = '' 57 | - ./release.ps1 $env:BITBUCKET_DEPLOYMENT_ENVIRONMENT 58 | 59 | # Legacy Delivery 60 | # - ./TasksLocal/delivery.ps1 $env:BITBUCKET_DEPLOYMENT_ENVIRONMENT 61 | 62 | runs-on: 63 | - windows 64 | 65 | - step: 66 | name: Deploy to production 67 | runs-on: 68 | - windows 69 | deployment: Production 70 | trigger: manual 71 | script: 72 | - $env:DOCKER_HOST = '' 73 | - ./release.ps1 $env:BITBUCKET_DEPLOYMENT_ENVIRONMENT 74 | 75 | # Legacy Delivery 76 | # - ./TasksLocal/delivery.ps1 $env:BITBUCKET_DEPLOYMENT_ENVIRONMENT 77 | -------------------------------------------------------------------------------- /orchestration/ado/CI-Only/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started-yaml 2 | # https://docs.microsoft.com/en-us/azure/devops/pipelines/process/variables 3 | # https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/hosted?view=vsts&tabs=yaml 4 | 5 | name: $(Rev:r) 6 | # name: $(TeamProject)_$(BuildDefinitionName)_$(SourceBranchName)_$(Date:yyyyMMdd)$(Rev:.r) 7 | 8 | pool: 9 | vmImage: 'windows-latest' 10 | # vmImage: 'windows-2019' 11 | 12 | trigger: 13 | branches: 14 | include: 15 | - '*' 16 | 17 | # For a private pool, in this example, named Private requiring the capability of PowerShell 18 | #pool: 19 | # name: Azure 20 | # demands: PowerShell 21 | 22 | # or pool with no demands 23 | #pool: Default 24 | 25 | variables: 26 | - group: Git-Reader-for-Branch-Clean-up 27 | # Must explicitely load secrets into a variable that is NOT the same as the variable itself, i.e. name cannot be GIT_PASSWORD 28 | - name: gitPass 29 | value: $[variables.GIT_PASSWORD] 30 | 31 | steps: 32 | - script: automation\entry.bat "$(Build.BuildNumber)" "$env:Build_SourceBranchName" "staging@$env:Build_ArtifactStagingDirectory" 33 | env: 34 | GIT_USERNAME: $[variables.GIT_USERNAME] 35 | GIT_PASSWORD: $(gitPass) 36 | 37 | # For installed instance of CDAF, in the agents user profile in this example 38 | # - script: "%USERPROFILE%\\.cdaf\\entry.bat \"$(Build.BuildNumber)\" \"$(Build.SourceBranchName)\" \"staging@$(Build.ArtifactStagingDirectory)\"" 39 | 40 | # Require explicit exit code if using a multi-line script 41 | # - script: | 42 | # $env:READ_ONLY_PAT=$(READ_ONLY_PAT) 43 | # ~/cdaf/processor/entry.ps1 "$env:Build_BuildNumber" "$env:Build_SourceBranchName" "staging@$env:Build_ArtifactStagingDirectory" 44 | # $LASTEXITCODE=$? 45 | # if ( $LASTEXITCODE != "0" ) { exit $$LASTEXITCODE } 46 | 47 | # env: 48 | # MAVEN_ARTIFACT_TOKEN: $(MAVEN_ARTIFACT_TOKEN) 49 | 50 | #- task: PublishTestResults@2 51 | # inputs: 52 | #testResultsFormat: 'JUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest 53 | #testResultsFiles: '**/TEST-*.xml' 54 | #searchFolder: '$(System.DefaultWorkingDirectory)' # Optional 55 | #mergeTestResults: true # Optional 56 | #failTaskOnFailedTests: true # Optional 57 | #testRunTitle: # Optional 58 | #buildPlatform: # Optional 59 | #buildConfiguration: # Optional 60 | #publishRunAttachments: true # Optional 61 | 62 | - task: PublishBuildArtifacts@1 63 | #ArtifactName: 'drop' 64 | #publishLocation: 'Container' -------------------------------------------------------------------------------- /provisioning/sqlCreateDB.ps1: -------------------------------------------------------------------------------- 1 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 2 | function executeExpression ($expression) { 3 | $error.clear() 4 | Write-Host "$expression" 5 | try { 6 | $output = Invoke-Expression $expression 7 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 8 | } catch { echo $_.Exception|format-list -force; exit 2 } 9 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 10 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 11 | return $output 12 | } 13 | 14 | # Reset $LASTEXITCODE 15 | cmd /c exit 0 16 | 17 | $scriptName = 'sqlCreateDB.ps1' 18 | 19 | Write-Host; Write-Host "[$scriptName] ---------- start ----------" 20 | $dbName = $args[0] 21 | if ($dbName) { 22 | Write-Host "[$scriptName] dbName : $dbName" 23 | } else { 24 | Write-Host "[$scriptName] dbName not supplied, exiting with code 100" 25 | exit 100 26 | } 27 | 28 | $dbOwner = $args[1] 29 | if ($dbOwner) { 30 | Write-Host "[$scriptName] dbOwner : $dbOwner" 31 | } else { 32 | Write-Host "[$scriptName] dbOwner : (not supplied)" 33 | } 34 | 35 | $dbhost = $args[2] 36 | if ($dbhost) { 37 | Write-Host "[$scriptName] dbhost : $dbhost" 38 | } else { 39 | $dbhost = '.' 40 | Write-Host "[$scriptName] dbhost : $dbhost (default)" 41 | } 42 | 43 | Write-Host 44 | # Load the assemblies 45 | executeExpression '[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")' 46 | executeExpression '[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement")' 47 | 48 | Write-Host 49 | $srv = executeExpression "new-Object Microsoft.SqlServer.Management.Smo.Server(`"$dbhost`")" 50 | if ( $srv ) { 51 | executeExpression "`$srv | select Urn" 52 | } else { 53 | Write-Host "[$scriptName] Server $dbhost not found!, Exit with code 103"; exit 103 54 | } 55 | 56 | Write-Host 57 | 58 | $db = executeExpression "New-Object Microsoft.SqlServer.Management.Smo.Database(`$srv, `"$dbName`")" 59 | executeExpression "`$db | select name" 60 | executeExpression "`$db.Create()" 61 | if ($dbOwner) { 62 | if ($dbOwner -eq $env:UserName) { 63 | Write-Host "[$scriptName] Requested owner is current user, no action taken." 64 | } else { 65 | executeExpression "`$db.SetOwner(`"$dbOwner`", `$True)" 66 | } 67 | } 68 | 69 | Write-Host 70 | executeExpression "`$srv.databases | select name" 71 | 72 | Write-Host 73 | Write-Host "[$scriptName] ---------- stop ----------" 74 | -------------------------------------------------------------------------------- /provisioning/GetExecutable.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$url, 3 | [string]$mediaDir, 4 | [string]$runTime, 5 | [string]$proxy 6 | ) 7 | $scriptName = 'GetExecutable.ps1' 8 | 9 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 10 | function executeExpression ($expression) { 11 | $error.clear() 12 | Write-Host "$expression" 13 | try { 14 | Invoke-Expression $expression 15 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 16 | } catch { echo $_.Exception|format-list -force; exit 2 } 17 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 18 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 19 | } 20 | 21 | Write-Host "`n[$scriptName] ---------- start ----------" 22 | if ($url) { 23 | Write-Host "[$scriptName] url : $url" 24 | } else { 25 | $url = 'http://cdaf.io/static/app/downloads/Database.exe' 26 | Write-Host "[$scriptName] url : $url (default)" 27 | } 28 | 29 | if ($mediaDir) { 30 | Write-Host "[$scriptName] mediaDir : $mediaDir" 31 | } else { 32 | $mediaDir = "$env:TEMP" 33 | Write-Host "[$scriptName] mediaDir : $mediaDir (default)" 34 | } 35 | 36 | if ($runTime) { 37 | Write-Host "[$scriptName] runTime : $runTime" 38 | } else { 39 | $runTime = '$env:windir' 40 | Write-Host "[$scriptName] runTime : $runTime (default)" 41 | } 42 | 43 | if ($proxy) { 44 | Write-Host "[$scriptName] proxy : $proxy`n" 45 | executeExpression "[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('$proxy')" 46 | } else { 47 | Write-Host "[$scriptName] proxy : (not supplied)" 48 | } 49 | 50 | $file = Split-Path -Path $url -Leaf 51 | 52 | if (!( Test-Path $mediaDir )) { 53 | Write-Host "[$scriptName] mkdir $mediaDir" 54 | mkdir $mediaDir 55 | } 56 | 57 | Write-Host 58 | $fullpath = $mediaDir + '\' + $file 59 | if ( Test-Path $fullpath ) { 60 | Write-Host "[$scriptName] $fullpath exists, download not required" 61 | } else { 62 | Write-Host "[$scriptName] $file does not exist in $mediaDir, listing contents" 63 | try { 64 | Get-ChildItem $mediaDir | Format-Table name 65 | if(!$?) { $fullpath = listAndContinue } 66 | } catch { $fullpath = listAndContinue } 67 | 68 | Write-Host "[$scriptName] Attempt download" 69 | executeExpression "(New-Object System.Net.WebClient).DownloadFile('$url', '$fullpath')" 70 | } 71 | 72 | executeExpression "Copy-Item `"$fullpath`" `"$runTime`"" 73 | 74 | Write-Host "`n[$scriptName] ---------- stop ----------" 75 | -------------------------------------------------------------------------------- /orchestration/bamboo-specs/bamboo.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | 4 | plan: 5 | project-key: REF 6 | key: WUC 7 | name: CDAf Windows Publication 8 | 9 | stages: 10 | - Build Stage: 11 | - Build Job 12 | 13 | Build Job: 14 | tasks: 15 | - script: 16 | interpreter: powershell 17 | scripts: | # Use latest Published CDAF 18 | . { iwr -useb https://cdaf.io/static/app/downloads/cdaf.ps1 } | iex 19 | .\\automation\\entry.bat ${bamboo.buildNumber} ${bamboo.repository.branch.name} 20 | 21 | # scripts: | # Edge version from GitHub 22 | # $env:CDAF_PATH = '.\automation' 23 | # . { iwr -useb https://raw.githubusercontent.com/cdaf/windows/master/install.ps1 } | iex 24 | # .\\automation\\entry.bat ${bamboo.buildNumber} ${bamboo.repository.branch.name} 25 | 26 | # scripts: | # "In-source" implemenation 27 | # .\\automation\\entry.bat ${bamboo.buildNumber} ${bamboo.repository.branch.name} 28 | 29 | artifacts: 30 | - name: Package 31 | pattern: 'release.ps1' 32 | shared: true 33 | 34 | --- 35 | version: 2 36 | 37 | deployment: 38 | name: WU-CDM 39 | source-plan: REF-WUC 40 | 41 | release-naming: 42 | next-version-name: ${bamboo.buildNumber} 43 | 44 | environments: 45 | - TEST 46 | - UAT 47 | - PROD 48 | 49 | TEST: 50 | triggers: 51 | - build-success 52 | tasks: 53 | - clean 54 | - artifact-download: 55 | destination: ${bamboo.working.directory} 56 | - script: 57 | interpreter: powershell 58 | scripts: 59 | - ${bamboo.build.working.directory}\\release.ps1 ${bamboo.deploy.environment} ${bamboo.deploy.release} 60 | - if ( $LASTEXITCODE -ne 0 ) { throw "Script failed with LASTEXITCODE = $LASTEXITCODE" } 61 | 62 | UAT: 63 | triggers: 64 | - environment-success: TEST 65 | tasks: 66 | - clean 67 | - artifact-download: 68 | destination: ${bamboo.working.directory} 69 | - script: 70 | interpreter: powershell 71 | scripts: 72 | - ${bamboo.build.working.directory}\\release.ps1 ${bamboo.deploy.environment} ${bamboo.deploy.release} 73 | - if ( $LASTEXITCODE -ne 0 ) { throw "Script failed with LASTEXITCODE = $LASTEXITCODE" } 74 | 75 | PROD: 76 | tasks: 77 | - clean 78 | - artifact-download: 79 | destination: ${bamboo.working.directory} 80 | - script: 81 | interpreter: powershell 82 | scripts: 83 | - ${bamboo.build.working.directory}\\release.ps1 ${bamboo.deploy.environment} ${bamboo.deploy.release} 84 | - if ( $LASTEXITCODE -ne 0 ) { throw "Script failed with LASTEXITCODE = $LASTEXITCODE" } 85 | -------------------------------------------------------------------------------- /provisioning/setInternetProxy.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$httpProxy, 3 | [string]$automaticeConfigurationScript 4 | ) 5 | 6 | cmd /c "exit 0" 7 | $scriptName = 'setInternetProxy.ps1' 8 | 9 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 10 | function executeExpression ($expression) { 11 | $error.clear() 12 | Write-Host "[$scriptName] $expression" 13 | try { 14 | Invoke-Expression $expression 15 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 16 | } catch { echo $_.Exception|format-list -force; exit 2 } 17 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 18 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 19 | } 20 | 21 | Write-Host "`n[$scriptName] ---------- start ----------`n" 22 | if ($httpProxy) { 23 | Write-Host "[$scriptName] httpProxy : $httpProxy (can be space separated list)" 24 | } else { 25 | if ($env:http_proxy) { 26 | $httpProxy = $env:http_proxy 27 | Write-Host "[$scriptName] httpProxy : $httpProxy (not passed, but derived from `$env:http_proxy)" 28 | } 29 | } 30 | 31 | if ($automaticeConfigurationScript) { 32 | Write-Host "[$scriptName] automaticeConfigurationScript : $automaticeConfigurationScript" 33 | } else { 34 | Write-Host "[$scriptName] automaticeConfigurationScript : (not supplied)" 35 | } 36 | 37 | if ($httpProxy) { 38 | Write-Host "[$scriptName] httpProxy : $httpProxy (can be space separated list)" 39 | executeExpression "[system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('$httpProxy')" 40 | 41 | $protocol,$prefix,$port = $httpProxy.split(':') 42 | $address = $prefix.Replace('/', '') 43 | $regKey = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" 44 | executeExpression "Set-ItemProperty -path '$regKey' ProxyEnable -value 1" 45 | executeExpression "Set-ItemProperty -path '$regKey' ProxyServer -value '${address}:${port}'" 46 | 47 | Write-Host "`n[$scriptName] List current settings before changing`n" 48 | executeExpression "netsh winhttp show proxy" 49 | executeExpression "netsh winhttp set proxy '${address}:${port}'" 50 | 51 | if ($automaticeConfigurationScript) { 52 | executeExpression "Set-ItemProperty -path $regKey AutoConfigURL -Value $automaticeConfigurationScript" 53 | } 54 | } else { 55 | Write-Host "[$scriptName] httpProxy not passed and unable to derive from `$env:http_proxy, exit without attempting any changes" -ForegroundColor 'Yellow' 56 | } 57 | 58 | Write-Host "`n[$scriptName] ---------- stop ----------" 59 | $error.clear() 60 | exit 0 -------------------------------------------------------------------------------- /provisioning/addUserToLocalGroup.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$group, 3 | [string]$userName, 4 | [string]$domain 5 | ) 6 | 7 | cmd /c "exit 0" 8 | $Error.Clear() 9 | 10 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 11 | function executeExpression ($expression) { 12 | Write-Host "[$(Get-Date)] $expression" 13 | try { 14 | Invoke-Expression $expression 15 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; $error ; exit 1111 } 16 | } catch { Write-Output $_.Exception|format-list -force; $error ; exit 1112 } 17 | if ( $LASTEXITCODE ) { 18 | if ( $LASTEXITCODE -ne 0 ) { 19 | Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red ; $error ; exit $LASTEXITCODE 20 | } else { 21 | if ( $error ) { 22 | Write-Host "[$scriptName][WARN] $Error array populated by `$LASTEXITCODE = $LASTEXITCODE error follows...`n" -ForegroundColor Yellow 23 | $error 24 | } 25 | } 26 | } else { 27 | if ( $error ) { 28 | Write-Host "[$scriptName] `$error[] = $error"; exit 1113 29 | } 30 | } 31 | } 32 | 33 | $scriptName = 'addUserToLocalGroup.ps1' 34 | 35 | Write-Host "`n[$scriptName] ---------- start ----------" 36 | if ($group) { 37 | Write-Host "[$scriptName] group : $group" 38 | } else { 39 | $group = 'Remote Management Users' 40 | Write-Host "[$scriptName] group : $group (default)" 41 | } 42 | 43 | if ($userName) { 44 | Write-Host "[$scriptName] userName : $userName" 45 | } else { 46 | $userName = 'Deployer' 47 | Write-Host "[$scriptName] userName : $userName (default)" 48 | } 49 | 50 | if ($domain) { 51 | Write-Host "[$scriptName] domain : $domain" 52 | } else { 53 | Write-Host "[$scriptName] domain : not supplied, will treat as local machine (workgroup)" 54 | } 55 | 56 | if ($domain) { 57 | Write-Host 58 | Write-Host "[$scriptName] Add $domain/$userName to local group $group." 59 | $de = executeExpression "[ADSI]`"WinNT://$env:computername/$group,group`"" 60 | executeExpression "`$de.psbase.Invoke(`"Add`",([ADSI]`"WinNT://$domain/$userName`").path)" 61 | } else { 62 | if ( $userName.StartsWith('.\')) { 63 | $userName = $userName.Substring(2) # Remove the .\ prefix 64 | } 65 | Write-Host "[$scriptName] Add $userName to local group $group." 66 | $argList = "localgroup `"$group`" $userName /add" 67 | Write-Host "[$scriptName] Start-Process net -ArgumentList $argList -PassThru -Wait" 68 | $proc = Start-Process net -ArgumentList $argList -PassThru -Wait 69 | if ( $proc.ExitCode -ne 0 ) { 70 | Write-Host "`n[$scriptName] Exit with `$LASTEXITCODE $($proc.ExitCode)`n" 71 | exit $proc.ExitCode 72 | } 73 | } 74 | 75 | Write-Host "`n[$scriptName] ---------- stop ----------" 76 | -------------------------------------------------------------------------------- /samples/all/automation-solution/storeForArtifact.txt: -------------------------------------------------------------------------------- 1 | # StoreForArtifact 2 | # Comments begin with # and will be ignored. 3 | # Section Labels begin with [ and will be ignored. 4 | # Empty lines will be ignored. 5 | # 6 | # To copy an artifact to the artifacts root directory, simply list it as follows: 7 | # \bin\Release\MyArtifactFile.exe 8 | # 9 | # To copy an artifact to the artifacts root directory and perform a rename, include the 10 | # filename after the pipe. 11 | # \bin\Release\MyArtifactFile.exe | MyRenamedFile.exe 12 | # 13 | # To copy an artifact to a specific sub-directory under the artifacts root directory, 14 | # use a pipe seperator to indicate the sub-directory. 15 | # \bin\Release\MyArtifactFile.exe | binaries 16 | # 17 | # To copy an artifact to a specific sub-directory under the artifacts root directory 18 | # AND perform a rename, include the filename after the sub-directory. 19 | # \bin\Release\MyArtifactFile.exe | binaries\MyRenamedFile.exe 20 | # 21 | # Wildcards may be used when copying files. To copy files from a target directory based 22 | # on wildcards, just specify the pattern in the source side. 23 | # \bin\Release\* | binaries\Release 24 | # \bin\Release\*.dll | binaries\ReleaseDLLs 25 | # 26 | # To zip a directory under the artifact workbench (or the workbench itself) simply pass 27 | # in that value as below. This will place a bin.zip under ARTIFACT_WORKBENCH 28 | # \bin 29 | # 30 | # To zip a directory under the artifact workbench (or the workbench itself) and specify 31 | # an output directory (and optionally, a filename) use the following entry format. 32 | # \bin | zips\binaries.zip 33 | # 34 | # By default, the filename will be analyzed to determine if the submitted name should be 35 | # handled as a directory or as a file based on the presence of a period in the name. In 36 | # the case of a directory that has periods, or a file that lacks an extension, this default 37 | # behavior will fail. To override the default and explicitly state whether or not a file 38 | # is a directory or a file, add a suffix of -d or -f to the end of the path. 39 | # \obj\Release\Package\PackageTmp\* -d | -d 40 | # \ -d | zips\.zip -f 41 | # 42 | # All values will be trimmed before being used in the application, so use whitespace as desired. 43 | 44 | [PROJECT_LABEL] 45 | \obj\Release\Package\PackageTmp\* -d | -d 46 | 47 | [zips] 48 | artifacts\ -d | zips\.zip -f -------------------------------------------------------------------------------- /provisioning/addPath.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$directoryName, 3 | [string]$level 4 | ) 5 | 6 | cmd /c "exit 0" 7 | $Error.Clear() 8 | 9 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 10 | function executeExpression ($expression) { 11 | Write-Host "[$(Get-Date)] $expression" 12 | try { 13 | Invoke-Expression $expression 14 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; $error ; exit 1111 } 15 | } catch { Write-Output $_.Exception|format-list -force; $error ; exit 1112 } 16 | if ( $LASTEXITCODE ) { 17 | if ( $LASTEXITCODE -ne 0 ) { 18 | Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red ; $error ; exit $LASTEXITCODE 19 | } else { 20 | if ( $error ) { 21 | Write-Host "[$scriptName][WARN] $Error array populated by `$LASTEXITCODE = $LASTEXITCODE error follows...`n" -ForegroundColor Yellow 22 | $error 23 | } 24 | } 25 | } else { 26 | if ( $error ) { 27 | Write-Host "[$scriptName] `$error[] = $error"; exit 1113 28 | } 29 | } 30 | } 31 | 32 | $scriptName = 'addPath.ps1' 33 | Write-Host "`n[$scriptName] ---------- start ----------" 34 | if ($directoryName) { 35 | Write-Host "[$scriptName] directoryName : $directoryName" 36 | } else { 37 | Write-Host "[$scriptName] directoryName not supplied, exiting!" 38 | exit 2365 39 | } 40 | 41 | if ($level) { 42 | Write-Host "[$scriptName] level : $level (Choices are Machine or User)" 43 | } else { 44 | $level = 'Machine' 45 | Write-Host "[$scriptName] level : $level (Default, choices are Machine or User)" 46 | } 47 | 48 | $elementInPath = $false 49 | # Append Directory to PATH if it is not already in the path 50 | $currentPath = [Environment]::GetEnvironmentVariable('Path', $level) 51 | if ( $currentPath ) { 52 | foreach ( $item in $currentPath.split(';') ) { 53 | if ( $item -eq $directoryName ) { 54 | $elementInPath = $true 55 | } 56 | } 57 | if ( $elementInPath ) { 58 | Write-Host "`n[$scriptName] directoryName $directoryName already exists in $level path`n" 59 | } else { 60 | Write-Host 61 | executeExpression "[Environment]::SetEnvironmentVariable(`'Path`', `$currentPath + `";$directoryName`", `'$level`')" 62 | Write-Host 63 | } 64 | }else { 65 | Write-Host 66 | executeExpression "[Environment]::SetEnvironmentVariable(`'Path`', `"$directoryName`", `'$level`')" 67 | Write-Host 68 | } 69 | 70 | # Reload the path (without logging off and back on) 71 | $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") 72 | 73 | Write-Host "[$scriptName] Complete path (User and Machine) is now ..." 74 | foreach ($item in ($env:PATH).split(';')) { 75 | Write-Host "[$scriptName] $item" 76 | } 77 | 78 | Write-Host "`n[$scriptName] ---------- stop -----------`n" 79 | -------------------------------------------------------------------------------- /samples/all/automation-solution/tasksRunLocal.tsk: -------------------------------------------------------------------------------- 1 | Write-Host "CDAF Version : $(& $CDAF_CORE/capabilities.ps1 cdaf)" 2 | 3 | Write-Host "12-factor approach uses environment variables, these would be set by the CI/CD tooling`n" -ForegroundColor Magenta 4 | ASSIGN $env:EXAMPLE_SECRET_1 = 'Shhh,Passw0Rd!' 5 | ASSIGN $env:EXAMPLE_SECRET_2 = 'Shhh,secret' 6 | 7 | Write-Host "Variable checklist" -ForegroundColor Magenta 8 | VARCHK 9 | 10 | Write-Host "Load a property file to memory`n" -ForegroundColor Magenta 11 | PROPLD manifest.txt 12 | 13 | Write-Host "Reveal values when assigning to variable`n" -ForegroundColor Magenta 14 | Write-Host " `$var_load = $var_load" 15 | Write-Host " `$list = $list" 16 | Write-Host " `$empty_var = $empty_var" 17 | Write-Host " `$null_var = $null_var" 18 | Write-Host " `$null = $null" 19 | 20 | ASSIGN $resolvedVarInVar = $var_load 21 | ASSIGN $resolvedStringInVar = $list 22 | ASSIGN $resolvedEmptyInVar = $empty_var 23 | ASSIGN $resolvedNullInVar = $null_var 24 | ASSIGN $resolvedNullVar = $null 25 | 26 | Write-Host "Keep a copy of the tokenised file`n" -ForegroundColor Magenta 27 | MAKDIR check 28 | VECOPY example.yaml check 29 | 30 | Write-Host "Detokenise a setting file`n" -ForegroundColor Magenta 31 | DETOKN example.yaml 32 | 33 | Write-Host "empty_var token is preserved because no match will be found, while null_var contains a reference to `$null" -ForegroundColor Magenta 34 | cat example.yaml 35 | 36 | Write-Host "Detokenise setting file using ad-hoc environment variable, only using where variable manipulation is required.`n" -ForegroundColor Magenta 37 | REPLAC example.yaml @secret@ $env:EXAMPLE_SECRET_1 38 | cat example.yaml 39 | 40 | Write-Host "Detokenise setting file using environment variable as defined in CM, this is the recommended method for applying secrets.`n" -ForegroundColor Magenta 41 | $env:CDAF_OVERRIDE_TOKEN = '@' 42 | DETOKN example.yaml $TARGET resolve 43 | 44 | Write-Host "empty_var token is preserved because no match will be found, while null_var will result in an empty property" -ForegroundColor Magenta 45 | cat example.yaml 46 | 47 | Write-Host "Detokenise setting file, revealing resolved property list = $list, csv = $csv`n" -ForegroundColor Magenta 48 | $env:CDAF_OVERRIDE_TOKEN = '!' 49 | DETOKN example.yaml $TARGET reveal 50 | 51 | Write-Host "empty_var token is preserved because no match will be found, while null_var will result in an empty property" -ForegroundColor Magenta 52 | cat example.yaml 53 | 54 | Write-Host "Process a comma separated list as array`n" -ForegroundColor Magenta 55 | Write-Host "`$csv = $csv" 56 | foreach ($item in $csv.Split(',')) { Write-Host " [ $item ]" } 57 | 58 | Write-Host "Detokenise file outside of workspace`n" -ForegroundColor Magenta 59 | cd check 60 | DETOKN example.yaml 61 | 62 | Write-Host "Execute outside of WORKSPACE" 63 | cd $TMPDIR 64 | PROPLD $WORKSPACE\manifest.txt 65 | -------------------------------------------------------------------------------- /orchestration/ado/Multi-stage/templates/azure-pipelines-build-template.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - job: Build 3 | displayName: ${{ parameters.displayName }} 4 | pool: 5 | vmImage: windows-latest 6 | # vmImage: windows-2019 7 | 8 | # pool: # Self-hosted Pool Name 9 | # name: Default 10 | # demands: Agent.OS -equals Windows_NT 11 | 12 | steps: 13 | # - task: PowerShell@2 14 | # displayName: Diag 15 | # inputs: 16 | # workingDirectory: $(System.ArtifactsDirectory)/drop 17 | # targetType: inline 18 | # script: dir ; systeminfo 19 | 20 | - task: PowerShell@2 21 | displayName: CDAF Release Build 22 | # URL and user are not likely to be set as secret, so an explicit mapping is not required, but included for reference 23 | # env: 24 | # GIT_URL: $(GIT_URL) 25 | # GIT_USER: $(GIT_USER) 26 | # GIT_PASS: $(GIT_PASS) 27 | inputs: 28 | 29 | targetType: 'inline' # Use latest published version 30 | script: | 31 | . { iwr -useb https://cdaf.io/static/app/downloads/cdaf.ps1 } | iex 32 | .\automation\entry.ps1 $(Build.BuildNumber) $(Build.SourceBranch) staging@$(Build.ArtifactStagingDirectory) 33 | 34 | # targetType: 'inline' # Use edge CDAF version from GitHub 35 | # script: | 36 | # . { iwr -useb https://raw.githubusercontent.com/cdaf/windows/master/install.ps1 } | iex 37 | # .\automation\entry.ps1 $(Build.BuildNumber) $(Build.SourceBranch) staging@$(Build.ArtifactStagingDirectory) 38 | 39 | # targetType: 'inline' # Use a specific CDAF version 40 | # script: | 41 | # iwr -useb http://cdaf.io/static/app/downloads/WU-CDAF-2.5.3.zip -OutFile WU_CDAF.zip 42 | # Expand-Archive WU_CDAF.zip 43 | # .\WU_CDAF\automation\entry.ps1 $(Build.BuildNumber) $(Build.SourceBranch) staging@$(Build.ArtifactStagingDirectory) 44 | 45 | # "In-source" implemenation 46 | # targetType: filePath 47 | # filePath: ./automation/entry.ps1 48 | # arguments: $(Build.BuildNumber) $(Build.SourceBranch) staging@$(Build.ArtifactStagingDirectory) 49 | 50 | # - task: PublishTestResults@2 51 | # condition: succeededOrFailed() 52 | # inputs: 53 | # testResultsFormat: 'JUnit' # Options: JUnit, NUnit, VSTest, xUnit, cTest 54 | # testResultsFiles: '**/test-results/*.xml' 55 | # searchFolder: '$(System.DefaultWorkingDirectory)' # Optional 56 | # mergeTestResults: true # Optional 57 | # failTaskOnFailedTests: true # Optional 58 | # testRunTitle: Checkov Results # Optional 59 | # buildPlatform: # Optional 60 | # buildConfiguration: # Optional 61 | # publishRunAttachments: true # Optional 62 | 63 | - task: PublishBuildArtifacts@1 64 | -------------------------------------------------------------------------------- /provisioning/installAzureRM.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [String]$interface 3 | ) 4 | $scriptName = 'installAzureRM.ps1' 5 | 6 | # Retry logic for connection issues, i.e. "Cannot retrieve the dynamic parameters for the cmdlet. PowerShell Gallery is currently unavailable. Please try again later." 7 | # Includes warning for "Cannot find a variable with the name 'PackageManagementProvider'. Cannot find a variable with the name 'SourceLocation'." 8 | function executeRetry ($expression) { 9 | $exitCode = 1 10 | $wait = 10 11 | $retryMax = 5 12 | $retryCount = 0 13 | while (( $retryCount -le $retryMax ) -and ($exitCode -ne 0)) { 14 | $exitCode = 0 15 | $error.clear() 16 | Write-Host "[$retryCount] $expression" 17 | try { 18 | Invoke-Expression $expression 19 | if(!$?) { Write-Host "[$scriptName] `$? = $?" -ForegroundColor Red; $exitCode = 1 } 20 | } catch { Write-Host "[$scriptName] $_" -ForegroundColor Red; $exitCode = 2 } 21 | if ( $error[0] ) { Write-Host "[$scriptName] Warning, message in `$error[0] = $error" -ForegroundColor Yellow; $error.clear() } # do not treat messages in error array as failure 22 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { $exitCode = $LASTEXITCODE; Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red; cmd /c "exit 0" } 23 | if ($exitCode -ne 0) { 24 | if ($retryCount -ge $retryMax ) { 25 | Write-Host "[$scriptName] Retry maximum ($retryCount) reached, exiting with `$LASTEXITCODE = $exitCode.`n" 26 | exit $exitCode 27 | } else { 28 | $retryCount += 1 29 | Write-Host "[$scriptName] Wait $wait seconds, then retry $retryCount of $retryMax" 30 | sleep $wait 31 | } 32 | } 33 | } 34 | } 35 | 36 | cmd /c "exit 0" 37 | # Use the CDAF provisioning helpers 38 | Write-Host "`n[$scriptName] ---------- start ----------" 39 | if ($interface) { 40 | Write-Host "[$scriptName] interface : $interface" 41 | } else { 42 | $interface = 'powershell' 43 | Write-Host "[$scriptName] interface : $interface (default)" 44 | } 45 | 46 | switch($interface){ 47 | 'powershell' { 48 | Write-Host "`n[$scriptName] Install Azure PowerShell commandlets`n" 49 | executeRetry 'Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Verbose -Force' 50 | executeRetry 'Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted' 51 | executeRetry 'Install-PackageProvider -Name NuGet -Confirm:$False' 52 | executeRetry 'Install-Module NuGet -Confirm:$False' 53 | executeRetry 'Install-Module AzureRM -Confirm:$False' 54 | executeRetry 'Install-Module Azure -Confirm:$False' 55 | } 56 | 'cli' { 57 | Write-Host "[$scriptName] Interface $interface is not yet implemented." 58 | } 59 | 60 | default { 61 | Write-Host "[$scriptName] Interface $interface is not supported! Exit with LASTEXITCODE 3657" 62 | exit 3657 63 | } 64 | } 65 | 66 | Write-Host "`n[$scriptName] ---------- stop ----------" 67 | exit 0 -------------------------------------------------------------------------------- /provisioning/addHOSTS.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$ipAddress, 3 | [string]$hostEntry 4 | ) 5 | 6 | # Initialise 7 | cmd /c "exit 0" 8 | $Error.Clear() 9 | $scriptName = 'addHOSTS.ps1' 10 | 11 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 12 | function executeExpression ($expression) { 13 | Write-Host "[$(Get-Date)] $expression" 14 | try { 15 | Invoke-Expression $expression 16 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; $error ; exit 1111 } 17 | } catch { Write-Output $_.Exception|format-list -force; $error ; exit 1112 } 18 | if ( $LASTEXITCODE ) { 19 | if ( $LASTEXITCODE -ne 0 ) { 20 | Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE " -ForegroundColor Red ; $error ; exit $LASTEXITCODE 21 | } else { 22 | if ( $error ) { 23 | Write-Host "[$scriptName][WARN] $Error array populated by `$LASTEXITCODE = $LASTEXITCODE error follows...`n" -ForegroundColor Yellow 24 | $error 25 | } 26 | } 27 | } else { 28 | if ( $error ) { 29 | Write-Host "[$scriptName] `$error[] = $error"; exit 1113 30 | } 31 | } 32 | } 33 | 34 | # In memory replacement performed to avoid dead-lock scenario when trying to use Get-Content / Set-Content commandlets 35 | Write-Host "`n[$scriptName] ---------- start ----------`n" 36 | if ($ipAddress) { 37 | Write-Host "[$scriptName] ipAddress : $ipAddress" 38 | } else { 39 | Write-Host "[$scriptName] ipAddress not supplied!" ; exit 777 40 | } 41 | 42 | if ($hostEntry) { 43 | Write-Host "[$scriptName] hostEntry : $hostEntry" 44 | } else { 45 | Write-Host "[$scriptName] hostEntry not supplied!" ; exit 776 46 | } 47 | 48 | $stringTest = $ipAddress.Split('.') 49 | $isFQDN = foreach ($item in $stringTest) { if (! ( $item -match "^\d+$" )) { Write-Output $item } } 50 | if ( $isFQDN ) { 51 | $ipAddress = ([System.Net.Dns]::GetHostAddresses($ipAddress))[0].IPAddressToString 52 | Write-Host "[$scriptName] Converted from FQDN to $ipAddress" 53 | } 54 | 55 | 56 | $hostsfile = 'C:\Windows\System32\drivers\etc\hosts' 57 | $transformed = @(Get-Content $hostsfile) 58 | $addEntry = $True 59 | $i = 0 60 | foreach ($record in $transformed) { 61 | if ($record -match " ${hostEntry}") { 62 | write-host "[$scriptName] Replacing $($transformed[$i]) with $ipAddress ${hostEntry}" 63 | $transformed[$i] = "$ipAddress ${hostEntry}" 64 | $addEntry = $False 65 | break 66 | } 67 | $i++ 68 | } 69 | 70 | if ( $addEntry ) { 71 | Write-Host "[$scriptName] Existing entry not found, create $ipAddress ${hostEntry}" 72 | $transformed += "$ipAddress ${hostEntry}" 73 | } 74 | 75 | Write-Host "[$scriptName] Replace $hostsfile" 76 | $stream = [System.IO.StreamWriter] $hostsfile 77 | foreach ($record in $transformed) { 78 | $stream.WriteLine($record) 79 | } 80 | $stream.close() 81 | 82 | executeExpression "Get-Content $hostsfile" 83 | 84 | Write-Host "`n[$scriptName] ---------- finish ----------`n" 85 | -------------------------------------------------------------------------------- /automation/remote/logWatch.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$logFile, 3 | [string]$stringMatch, 4 | [string]$waitTime 5 | ) 6 | 7 | cmd /c "exit 0" 8 | $scriptName = 'logWatch.ps1' 9 | 10 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 11 | function executeExpression ($expression) { 12 | $error.clear() 13 | Write-Host "$expression" 14 | try { 15 | Invoke-Expression $expression 16 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 17 | } catch { Write-Host $_.Exception|format-list -force; exit 2 } 18 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 19 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 20 | } 21 | 22 | Write-Host "`n[$scriptName] --- start ---" 23 | if ($logFile) { 24 | Write-Host "[$scriptName] logFile : $logFile" 25 | } else { 26 | Write-Host "[$scriptName] logFile not supplied, exit with `$LASTEXITCODE = 101"; exit 101 27 | } 28 | 29 | if ($stringMatch) { 30 | Write-Host "[$scriptName] stringMatch : $stringMatch" 31 | } else { 32 | Write-Host "[$scriptName] stringMatch not supplied, exit with `$LASTEXITCODE = 102"; exit 102 33 | } 34 | 35 | if ($waitTime) { 36 | Write-Host "[$scriptName] waitTime : $waitTime`n" 37 | } else { 38 | $waitTime = '60' 39 | Write-Host "[$scriptName] waitTime : $waitTime (default)`n" 40 | } 41 | 42 | $wait = 5 43 | $retryMax = [int]( $waitTime / $wait ) 44 | $retryCount = 0 45 | $lastLineNumber = 0 46 | $exitCode = 4365 47 | while (( $retryCount -le $retryMax ) -and ($exitCode -ne 0)) { 48 | sleep $wait 49 | if ( Test-Path $logFile ) { 50 | $output = $(cat $logFile) 51 | if ( $output ) { 52 | $lineCount = 1 53 | foreach ($line in $output -split "`r`n") { 54 | if ( $lineCount -gt $lastLineNumber ) { 55 | Write-Host "> $line" 56 | $lastLineNumber = $lineCount 57 | } 58 | $lineCount += 1 59 | } 60 | 61 | if ( Select-String -Pattern $stringMatch -InputObject $output ) { 62 | Write-Host "`n[$scriptName] stringMatch ($stringMatch) found." 63 | $exitCode = 0 64 | } 65 | if ( Select-String -Pattern 'CDAF_DELIVERY_FAILURE.' -InputObject $output ) { 66 | Write-Host "[$scriptName] Error Detected (CDAF_DELIVERY_FAILURE.) exit with error code 335" 67 | $exitCode = 335 68 | $retryCount = $retryMax 69 | } 70 | } else { 71 | Write-Host "[$scriptName] no output ..." 72 | } 73 | } else { 74 | Write-Host "[$scriptName] no output (log file does not exist) ..." 75 | } 76 | 77 | if ( $retryCount -ge $retryMax ) { 78 | Write-Host "[$scriptName] Maximum wait time ($waitTime) reached after $retryMax retries, exiting with code $waitTime (waitTime)" 79 | $exitCode = $waitTime 80 | } 81 | $retryCount += 1 82 | } 83 | 84 | Write-Host "`n[$scriptName] --- end ---" 85 | $error.clear() 86 | exit $exitCode 87 | -------------------------------------------------------------------------------- /samples/containerDeploy-custom-image/containerDeploy/bootstrapAgent.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$npmPackages 3 | ) 4 | 5 | cmd /c "exit 0" 6 | $scriptName = 'bootstrapAgent.ps1' 7 | 8 | 9 | # Consolidated Error processing function 10 | # required : error message 11 | # optional : exit code, if not supplied only error message is written 12 | function ERRMSG ($message, $exitcode) { 13 | if ( $exitcode ) { 14 | Write-Host "`n[$scriptName]$message" -ForegroundColor Red 15 | } else { 16 | Write-Warning "`n[$scriptName]$message" 17 | } 18 | if ( $error ) { 19 | $i = 0 20 | foreach ( $item in $Error ) 21 | { 22 | Write-Host "`$Error[$i] $item" 23 | $i++ 24 | } 25 | $Error.clear() 26 | } 27 | if ( $exitcode ) { 28 | if ( $env:CDAF_ERROR_DIAG ) { 29 | Write-Host "`n[$scriptName] Invoke custom diag `$env:CDAF_ERROR_DIAG = $env:CDAF_ERROR_DIAG`n" 30 | Invoke-Expression $env:CDAF_ERROR_DIAG 31 | } 32 | Write-Host "`n[$scriptName] Exit with LASTEXITCODE = $exitcode`n" -ForegroundColor Red 33 | exit $exitcode 34 | } 35 | } 36 | 37 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 38 | function executeExpression ($expression) { 39 | Write-Host "[$(Get-Date)] $expression" 40 | try { 41 | Invoke-Expression $expression 42 | if(!$?) { ERRMSG "[TRAP] `$? = $?" 1211 } 43 | } catch { 44 | $message = $_.Exception.Message 45 | $_.Exception | format-list -force 46 | $_.Exception.StackTrace 47 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { 48 | ERRMSG "[EXEC][EXCEPTION] $message" $LASTEXITCODE 49 | } else { 50 | ERRMSG "[EXEC][EXCEPTION] $message" 1212 51 | } 52 | } 53 | if ( $LASTEXITCODE ) { 54 | if ( $LASTEXITCODE -ne 0 ) { 55 | ERRMSG "[EXEC][EXIT] `$LASTEXITCODE is $LASTEXITCODE" $LASTEXITCODE 56 | } else { 57 | if ( $error ) { 58 | ERRMSG "[EXEC][WARN] `$LASTEXITCODE is $LASTEXITCODE, but standard error populated" 59 | } 60 | } 61 | } else { 62 | if ( $error ) { 63 | if ( $env:CDAF_IGNORE_WARNING -eq 'no' ) { 64 | ERRMSG "[EXEC][ERROR] `$env:CDAF_IGNORE_WARNING is 'no' so exiting" 1213 65 | } else { 66 | ERRMSG "[EXEC][WARN] `$LASTEXITCODE not set, but standard error populated" 67 | } 68 | } 69 | } 70 | } 71 | 72 | # Windows Command Execution combining standard error and standard out, with only non-zero exit code triggering error 73 | function EXECMD ($expression) { 74 | Write-Host "[$(Get-Date)] $expression" 75 | cmd /c "$expression 2>&1" 76 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { 77 | ERRMSG "[EXECMD][EXIT] `$LASTEXITCODE is $LASTEXITCODE" $LASTEXITCODE 78 | } 79 | } 80 | 81 | # This is a trivial example when could be just built in-line within Dockerfile, however, it is a example for more complex provisioning 82 | Write-Host "`n[$scriptName] ---------- start ----------" 83 | if ($npmPackages) { 84 | Write-Host "[$scriptName] npmPackages : $npmPackages" 85 | EXECMD "npm install -g $npmPackages" 86 | } else { 87 | Write-Host "[$scriptName] npmPackages : (not supplied, no action attempted)" 88 | } 89 | 90 | Write-Host "`n[$scriptName] ---------- stop ----------" 91 | -------------------------------------------------------------------------------- /automation/remote/winrmtest.ps1: -------------------------------------------------------------------------------- 1 | 2 | $scriptName = 'winrmtest.ps1' 3 | Write-Host 4 | Write-Host "[$scriptName] ---------- start ----------" 5 | Write-Host 6 | 7 | $vmHost = $args[0] 8 | if ( $vmHost ) { 9 | Write-Host "[$scriptName] vmHost : $vmHost" 10 | } else { 11 | Write-Host "[$scriptName] VM host not passed, exit with error code 100."; exit 100 12 | } 13 | 14 | $username = $args[1] 15 | if ( $username ) { 16 | Write-Host "[$scriptName] username : $username" 17 | } else { 18 | Write-Host "[$scriptName] Username not passed, exit with error code 101."; exit 101 19 | } 20 | 21 | $userpass = $args[2] 22 | if ( $userpass ) { 23 | Write-Host "[$scriptName] userpass : ***********" 24 | } else { 25 | Write-Host "[$scriptName] Password not passed, exit with error code 102."; exit 102 26 | } 27 | 28 | $successRequired = $args[3] 29 | if ( $successRequired ) { 30 | Write-Host "[$scriptName] successRequired : $successRequired" 31 | } else { 32 | $successRequired = 2 33 | Write-Host "[$scriptName] successRequired : $successRequired (default)" 34 | } 35 | 36 | $retries = $args[4] 37 | if ( $retries ) { 38 | Write-Host "[$scriptName] retries : $retries" 39 | } else { 40 | $retries = 5 41 | Write-Host "[$scriptName] retries : $retries (default)" 42 | } 43 | Write-Host 44 | 45 | # Add target host to trusted hosts list 46 | try { 47 | Set-WSManInstance -ResourceURI winrm/config/client -ValueSet @{TrustedHosts=$vmHost} 48 | } catch { 49 | Write-Host "[$scriptName] unable to add target as trusted host, assuming on domain, proceeding ..." 50 | } 51 | 52 | # Create a credential object with the user ID and userpass 53 | $securePassword = ConvertTo-SecureString $userpass -asplaintext -force 54 | $cred = New-Object System.Management.Automation.PSCredential ($username, $securePassword) 55 | $i = 0 56 | $timeout = 60 57 | $successCount = 0 58 | do { 59 | # Test connection and echo basic target details 60 | try { 61 | Invoke-Command -ComputerName $vmHost -credential $cred -SessionOption (New-PSSessionOption -SkipRevocationCheck -SkipCACheck -SkipCNCheck) { 62 | Write-Host 63 | Write-Host " RemotePowershell user : $(whoami)" 64 | Write-Host " RemotePowershell hostname : $(hostname)" 65 | } 66 | if($?) { $successCount ++ } 67 | } catch { Write-Host "[$scriptName] Invoke Exception thrown, $_"; exit 200 } 68 | 69 | if ($successCount -lt $successRequired) { 70 | $i++ 71 | if ( $i -le $retries) { 72 | Write-Host "[$scriptName] Success count $successCount/$successRequired, retry WinRM ($i/$retries) wait $timeout seconds before retry ..." 73 | sleep $timeout 74 | } else { 75 | Write-Host "[$scriptName] WinRM Connection failed after $retries tries, exit with error code 201" 76 | exit 201 77 | } 78 | } 79 | } # End of 'Do' 80 | until (( $i -gt $retries) -or ($successCount -ge $successRequired)) 81 | if ($successCount -ge $successRequired) { 82 | Write-Host "[$scriptName] Success count $successCount/$successRequired." 83 | } 84 | 85 | Write-Host 86 | Write-Host "[$scriptName] ---------- finish ----------" 87 | Write-Host 88 | 89 | # Clear the error array from any failed attempts 90 | $error.clear() 91 | -------------------------------------------------------------------------------- /automation/local/remoteTasks.ps1: -------------------------------------------------------------------------------- 1 | # executeExpression and ERRMSG inherited from delivery.ps1 2 | 3 | $scriptName = $myInvocation.MyCommand.Name 4 | 5 | Write-Host "`n[$scriptName] +---------------------------------+" 6 | Write-Host "[$scriptName] | Process Remotely Executed Tasks |" 7 | Write-Host "[$scriptName] +---------------------------------+" 8 | 9 | $ENVIRONMENT = $args[0] 10 | Write-Host "[$scriptName] ENVIRONMENT : $ENVIRONMENT" 11 | $BUILDNUMBER = $args[1] 12 | Write-Host "[$scriptName] BUILDNUMBER : $BUILDNUMBER" 13 | $SOLUTION = $args[2] 14 | Write-Host "[$scriptName] SOLUTION : $SOLUTION" 15 | $WORK_DIR_DEFAULT = $args[3] 16 | Write-Host "[$scriptName] WORK_DIR_DEFAULT : $WORK_DIR_DEFAULT" 17 | $OPT_ARG = $args[4] 18 | Write-Host "[$scriptName] OPT_ARG : $OPT_ARG" 19 | 20 | $propertiesFile = "CDAF.properties" 21 | $propName = "productVersion" 22 | try { 23 | $cdafVersion=$(& $WORK_DIR_DEFAULT\getProperty.ps1 $WORK_DIR_DEFAULT\$propertiesFile $propName) 24 | if(!$?){ taskWarning } 25 | } catch { exceptionExit 'GET_CDAF_VERSION_104' $_ } 26 | 27 | Write-Host "[$scriptName] CDAF Version : $cdafVersion" 28 | 29 | $WORKSPACE = (Get-Location).Path 30 | Write-Host "[$scriptName] WORKSPACE : $WORKSPACE" 31 | # list system info 32 | Write-Host "[$scriptName] Hostname : $(hostname)" 33 | Write-Host "[$scriptName] Whoami : $(whoami)" 34 | Write-Host "[$scriptName] pwd : $(pwd)" 35 | 36 | $propertiesFilter = 'propertiesForRemoteTasks\' + "$ENVIRONMENT*" 37 | 38 | $exitStatus = 0 39 | 40 | # Perform Remote Tasks for each environment defintion file 41 | 42 | if (-not(Test-Path $WORK_DIR_DEFAULT\$propertiesFilter)) { 43 | 44 | Write-Host "`n[$scriptName][WARN] Properties not found ($propertiesFilter) alter processSequence property to skip" -ForegroundColor Yellow 45 | 46 | } else { 47 | 48 | Write-Host "`n[$scriptName] Preparing to process deploy targets :`n" 49 | foreach ($propFile in (Get-ChildItem -Path $WORK_DIR_DEFAULT\$propertiesFilter)) { 50 | $propFilename = getFilename($propFile.ToString()) 51 | Write-Host "[$scriptName] $propFilename" 52 | } 53 | 54 | foreach ($propFile in (Get-ChildItem -Path $WORK_DIR_DEFAULT\$propertiesFilter)) { 55 | $propFilename = getFilename($propFile.ToString()) 56 | 57 | write-host "`n[$scriptName] --- Process Target $propFilename ---`n" -ForegroundColor Green 58 | executeExpression "& '$WORK_DIR_DEFAULT\remoteTasksTarget.ps1' '$ENVIRONMENT' '$SOLUTION' '$BUILDNUMBER' '$propFilename' '$WORK_DIR_DEFAULT' '$OPT_ARG'" 59 | if ( "$(pwd)" -ne $WORKSPACE ){ 60 | Write-Host "`n[$scriptName] Return to WORKSPACE" 61 | executeExpression " cd $WORKSPACE" 62 | } 63 | 64 | write-host "`n[$scriptName] --- Completed Target $propFilename ---`n" -ForegroundColor Green 65 | } 66 | 67 | if ( "$(pwd)" -ne $WORKSPACE ){ 68 | Write-Host "`n[$scriptName] Return to WORKSPACE" 69 | executeExpression " cd $WORKSPACE" 70 | } 71 | 72 | Write-Host "[$scriptName] +----------------------------------+" 73 | Write-Host "[$scriptName] | Competed Remotely Executed Tasks |" 74 | Write-Host "[$scriptName] +----------------------------------+" 75 | } 76 | 77 | exit 0 -------------------------------------------------------------------------------- /provisioning/installMSU.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$msuFile, 3 | [string]$opt_arg, 4 | [string]$reboot 5 | ) 6 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 7 | function executeExpression ($expression) { 8 | $error.clear() 9 | Write-Host "$expression" 10 | try { 11 | $output = Invoke-Expression $expression 12 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 13 | } catch { echo $_.Exception|format-list -force; exit 2 } 14 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 15 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 16 | return $output 17 | } 18 | 19 | $scriptName = 'installMSU.ps1' 20 | Write-Host "`n[$scriptName] Generic MSU installer" 21 | Write-Host "`n[$scriptName] ---------- start ----------" 22 | if ($msuFile) { 23 | Write-Host "[$scriptName] msuFile : $msuFile" 24 | } else { 25 | Write-Host "[$scriptName] MSI file not supplied, exiting with error code 1"; exit 1 26 | } 27 | Write-Host 28 | if ( Test-Path $msuFile ) { 29 | $fileName = Split-Path $msuFile -leaf 30 | } else { 31 | Write-Host "[$scriptName] $msuFile not found, exiting with error code 2"; exit 2 32 | } 33 | 34 | if ($opt_arg) { 35 | Write-Host "[$scriptName] opt_arg : $opt_arg" 36 | } else { 37 | Write-Host "[$scriptName] opt_arg : (not supplied)" 38 | } 39 | 40 | if ($reboot) { 41 | Write-Host "[$scriptName] reboot : $reboot" 42 | $optParm += "-reboot $reboot" 43 | $argList = @('/quiet') 44 | } else { 45 | $reboot = 'no' 46 | Write-Host "[$scriptName] reboot : $reboot (default)" 47 | $argList = @('/quiet', '/norestart') 48 | } 49 | 50 | if ($env:interactive) { 51 | Write-Host "[$scriptName] `$env:interactive : $env:interactive, run in current window" 52 | $sessionControl = '-PassThru -Wait -NoNewWindow' 53 | } else { 54 | $sessionControl = '-PassThru -Wait' 55 | } 56 | 57 | Write-Host 58 | 59 | try { 60 | 61 | $proc = executeExpression "Start-Process -FilePath `'$msuFile`' -ArgumentList `'$argList`' $sessionControl" 62 | 63 | if ( $proc.ExitCode -ne 0 ) { 64 | switch ($proc.ExitCode) { 65 | 2359302 { 66 | Write-Host "`n[$scriptName] Exit 2359302 MSU alreay installed, reboot maybe required.`n" 67 | } 68 | -2145124329 { 69 | Write-Host "`n[$scriptName] Exit -2145124329 MSU alreay installed.`n" 70 | } 71 | 3010 { 72 | Write-Host "`n[$scriptName] Exit 3010 The requested operation is successful. Changes will not be effective until the system is rebooted.`n" 73 | } 74 | default { 75 | Write-Host "`n[$scriptName] Install Failed, see log file (c:\windows\logs\CBS\CBS.log) for details, listing last 40 lines`n" 76 | executeExpression "Get-Content 'c:\windows\logs\CBS\CBS.log' | select -Last 40" 77 | Write-Host "`n[$scriptName] Exit with `$LASTEXITCODE $($proc.ExitCode)`n" 78 | exit $proc.ExitCode 79 | } 80 | } 81 | } 82 | } catch { 83 | Write-Host "[$scriptName] PowerShell Install Exception : $_" -ForegroundColor Red 84 | exit 200 85 | } 86 | 87 | Write-Host 88 | Write-Host "[$scriptName] ---------- stop -----------" 89 | Write-Host -------------------------------------------------------------------------------- /provisioning/sqlAddUserDB.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$dbName, 3 | [string]$dbUser, 4 | [string]$dbhost 5 | ) 6 | 7 | # Reset $LASTEXITCODE 8 | cmd /c exit 0 9 | 10 | $scriptName = 'sqlAddUserDB.ps1' 11 | 12 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 13 | function executeExpression ($expression) { 14 | $error.clear() 15 | Write-Host "$expression" 16 | try { 17 | $output = Invoke-Expression $expression 18 | if(!$?) { Write-Host "[$scriptName] `$? = $?"; exit 1 } 19 | } catch { echo $_.Exception|format-list -force; exit 2 } 20 | if ( $error ) { Write-Host "[$scriptName] `$error[0] = $error"; exit 3 } 21 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { Write-Host "[$scriptName] `$LASTEXITCODE = $LASTEXITCODE "; exit $LASTEXITCODE } 22 | return $output 23 | } 24 | 25 | Write-Host "`n[$scriptName] ---------- start ----------" 26 | if ($dbName) { 27 | Write-Host "[$scriptName] dbName : $dbName" 28 | } else { 29 | Write-Host "[$scriptName] dbName not supplied, exiting with code 100"; exit 100 30 | } 31 | 32 | if ($dbUser) { 33 | Write-Host "[$scriptName] dbUser : $dbUser" 34 | } else { 35 | Write-Host "[$scriptName] dbUser not supplied, exiting with code 101"; exit 101 36 | } 37 | 38 | if ($dbhost) { 39 | Write-Host "[$scriptName] dbhost : $dbhost" 40 | } else { 41 | $dbhost = '.' 42 | Write-Host "[$scriptName] dbhost : $dbhost (default)" 43 | } 44 | 45 | Write-Host "`n[$scriptName] Load the assemblies ...`n" 46 | executeExpression '[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")' 47 | executeExpression '[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.SqlWmiManagement")' 48 | 49 | # Rely on caller passing host or host\instance as they desire 50 | Write-Host "`n[$scriptName] Connect to the SQL Server instance ($dbhost) ...`n" 51 | $srv = executeExpression "new-Object Microsoft.SqlServer.Management.Smo.Server(`"$dbhost`")" 52 | if ( $srv ) { 53 | executeExpression "`$srv | select Urn" 54 | } else { 55 | Write-Host "[$scriptName] Server $dbhost not found!, Exit with code 103"; exit 103 56 | } 57 | 58 | Write-Host "`n[$scriptName] List current permissions for database ($dbName) ...`n" 59 | $db = executeExpression "`$srv.Databases[`"$dbName`"]" 60 | if ( $db ) { 61 | executeExpression "`$db | select Urn" 62 | executeExpression "`$db.EnumDatabasePermissions() | select Grantee, PermissionState" 63 | } else { 64 | Write-Host "[$scriptName] Database $dbName not found!, Exit with code 104"; exit 104 65 | } 66 | 67 | Write-Host "`n[$scriptName] List user permission before update ...`n" 68 | $usr = executeExpression "New-Object ('Microsoft.SqlServer.Management.Smo.User') (`$db, `"$dbUser`")" 69 | if ( $usr ) { 70 | executeExpression "`$usr | select Urn" 71 | executeExpression "`$usr.EnumObjectPermissions()" 72 | } else { 73 | Write-Host "[$scriptName] User $dbUser not found!, Exit with code 105"; exit 105 74 | } 75 | executeExpression "`$usr.Login = `$dbUser" 76 | executeExpression "`$usr.Create()" 77 | 78 | Write-Host "`n[$scriptName] List user and database permissions after update ...`n" 79 | executeExpression "`$usr.EnumObjectPermissions()" 80 | executeExpression "`$db.EnumDatabasePermissions() | select Grantee, PermissionState" 81 | 82 | Write-Host "`n[$scriptName] ---------- stop ----------" 83 | -------------------------------------------------------------------------------- /samples/executeSamples.ps1: -------------------------------------------------------------------------------- 1 | Param ( 2 | [string]$ACTION 3 | ) 4 | 5 | $scriptName = 'executeSamples.ps1' 6 | cmd /c "exit 0" 7 | 8 | 9 | # Consolidated Error processing function 10 | # required : error message 11 | # optional : exit code, if not supplied only error message is written 12 | function ERRMSG ($message, $exitcode) { 13 | if ( $exitcode ) { 14 | Write-Host "`n[$scriptName]$message" -ForegroundColor Red 15 | } else { 16 | Write-Warning "`n[$scriptName]$message" 17 | } 18 | if ( $error ) { 19 | $i = 0 20 | foreach ( $item in $Error ) 21 | { 22 | Write-Host "`$Error[$i] $item" 23 | $i++ 24 | } 25 | $Error.clear() 26 | } 27 | if ( $exitcode ) { 28 | if ( $env:CDAF_ERROR_DIAG ) { 29 | Write-Host "`n[$scriptName] Invoke custom diag `$env:CDAF_ERROR_DIAG = $env:CDAF_ERROR_DIAG`n" 30 | Invoke-Expression $env:CDAF_ERROR_DIAG 31 | } 32 | Write-Host "`n[$scriptName] Exit with LASTEXITCODE = $exitcode`n" -ForegroundColor Red 33 | exit $exitcode 34 | } 35 | } 36 | 37 | # Common expression logging and error handling function, copied, not referenced to ensure atomic process 38 | function executeExpression ($expression) { 39 | Write-Host "[$(Get-Date)] $expression" 40 | try { 41 | Invoke-Expression $expression 42 | if(!$?) { ERRMSG "[TRAP] `$? = $?" 1211 } 43 | } catch { 44 | $message = $_.Exception.Message 45 | $_.Exception | format-list -force 46 | $_.Exception.StackTrace 47 | if (( $LASTEXITCODE ) -and ( $LASTEXITCODE -ne 0 )) { 48 | ERRMSG "[EXEC][EXCEPTION] $message" $LASTEXITCODE 49 | } else { 50 | ERRMSG "[EXEC][EXCEPTION] $message" 1212 51 | } 52 | } 53 | if ( $LASTEXITCODE ) { 54 | if ( $LASTEXITCODE -ne 0 ) { 55 | ERRMSG "[EXEC][EXIT] `$LASTEXITCODE is $LASTEXITCODE" $LASTEXITCODE 56 | } else { 57 | if ( $error ) { 58 | ERRMSG "[EXEC][WARN] `$LASTEXITCODE is $LASTEXITCODE, but standard error populated" 59 | } 60 | } 61 | } else { 62 | if ( $error ) { 63 | if ( $env:CDAF_IGNORE_WARNING -eq 'no' ) { 64 | ERRMSG "[EXEC][ERROR] `$env:CDAF_IGNORE_WARNING is 'no' so exiting" 1213 65 | } else { 66 | ERRMSG "[EXEC][WARN] `$LASTEXITCODE not set, but standard error populated" 67 | } 68 | } 69 | } 70 | } 71 | 72 | Write-Host "`n[$scriptName] ---------- start ----------`n" 73 | Write-Host "[$scriptName] ACTION : $ACTION`n" 74 | 75 | if ( $ACTION -eq 'native' ) { 76 | $list = @('all', 'custom', 'feature-branch-environments', 'minimal', 'pre-post-processes') 77 | Write-Host "[$scriptName] ACTION = $ACTION, execute custom list:`n" 78 | } else { 79 | $list = Get-ChildItem -Directory 80 | Write-Host "[$scriptName] ACTION not set, execute default list:`n" 81 | } 82 | 83 | foreach ($dirName in $list) { 84 | Write-Host "[$scriptName] $dirName" 85 | } 86 | 87 | foreach ($dirName in $list) { 88 | Write-Host "`n[$scriptName] ---------- begin $dirName ----------`n" 89 | executeExpression "cd $dirName" 90 | executeExpression "..\..\automation\cdEmulate.bat" 91 | executeExpression "cd .." 92 | Write-Host "`n[$scriptName] ---------- end $dirName ----------" 93 | } 94 | 95 | Write-Host "`n[$scriptName] Sample test complete for:" 96 | foreach ($dirName in $list) { 97 | Write-Host " $dirName" 98 | } 99 | 100 | Write-Host "`n[$scriptName] ---------- stop ----------" 101 | $error.clear() 102 | exit 0 --------------------------------------------------------------------------------