diff --git a/.github/workflows/Check-pull-request-source-branch.yml b/.github/workflows/Check-pull-request-source-branch.yml
deleted file mode 100644
index 1d6bc9a1..00000000
--- a/.github/workflows/Check-pull-request-source-branch.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Check pull request source branch
-
-on:
- pull_request_target:
- types:
- - opened
- - reopened
- - synchronize
- - edited
-
-jobs:
- check-branches:
- runs-on: ubuntu-latest
- steps:
- - name: Check branches
- run: |
- if [ "${{ github.head_ref }}" != "develop" ] && [ "${{ github.base_ref }}" == "main" ]; then
- echo "Error: Pull requests to the main branch are only allowed from the develop branch. Please submit your pull request to the develop branch."
- exit 1
- fi
\ No newline at end of file
diff --git a/.github/workflows/CloseInactiveIssues.yml b/.github/workflows/GA_Close-Inactive-Issues.yml
similarity index 100%
rename from .github/workflows/CloseInactiveIssues.yml
rename to .github/workflows/GA_Close-Inactive-Issues.yml
diff --git a/.github/workflows/mega-linter.yml b/.github/workflows/GA_Mega-linter.yml
similarity index 100%
rename from .github/workflows/mega-linter.yml
rename to .github/workflows/GA_Mega-linter.yml
diff --git a/.github/workflows/GitFlow_Check-pull-request-source-branch.yml b/.github/workflows/GitFlow_Check-pull-request-source-branch.yml
new file mode 100644
index 00000000..38a49704
--- /dev/null
+++ b/.github/workflows/GitFlow_Check-pull-request-source-branch.yml
@@ -0,0 +1,183 @@
+# This workflow enforces GitFlow branch patterns by:
+# - Ensuring only hotfix/* branches can target main (release branches are handled automatically)
+# - Adding labels and comments to non-compliant PRs
+# - Automatically cleaning up when PRs are updated to comply
+
+name: GitFlow | Check PR Branch Pattern
+
+on:
+ pull_request_target:
+ types:
+ - opened
+ - reopened
+ - synchronize
+ - edited
+
+# Add explicit permissions
+permissions:
+ pull-requests: write
+ issues: write
+ contents: read
+
+env:
+ MAIN_BRANCH: "main"
+ DEVELOP_BRANCH: "develop"
+ VALID_PATTERNS: "^(release|hotfix)/"
+ LABEL_NAME: "invalid-branch"
+ ERROR_MESSAGE_IDENTIFIER: "Invalid Branch Pattern for main Branch"
+
+jobs:
+ check_branch:
+ runs-on: ubuntu-latest
+ steps:
+ # Step 1: Use GitHub Script for branch pattern validation (safer than shell)
+ - name: Check branch pattern
+ id: branch_check
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ result-encoding: string
+ script: |
+ // Get branch information from context
+ const headRef = context.payload.pull_request.head.ref;
+ const baseRef = context.payload.pull_request.base.ref;
+ const mainBranch = process.env.MAIN_BRANCH;
+ const validPattern = new RegExp(process.env.VALID_PATTERNS);
+
+ console.log(`Checking PR from '${headRef}' to '${baseRef}'`);
+
+ // Perform the validation in JavaScript instead of shell
+ if (baseRef === mainBranch) {
+ if (!validPattern.test(headRef)) {
+ console.log(`::error::❌ Invalid branch! PRs to main must come from hotfix/* or release/* branches. Please target the develop branch instead.`);
+ return 'invalid';
+ } else {
+ console.log(`::notice::✅ Branch pattern is valid: '${headRef}' → '${mainBranch}'`);
+ return 'valid';
+ }
+ } else {
+ console.log(`::notice::✅ Not targeting main branch, no pattern restrictions apply.`);
+ return 'not-main';
+ }
+
+ # Step 2: If the branch pattern is invalid, add a label and comment to the PR
+ - name: Handle invalid branch (label + comment)
+ if: steps.branch_check.outputs.result == 'invalid'
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { owner, repo } = context.repo;
+ const issue_number = context.payload.pull_request.number;
+ const label = process.env.LABEL_NAME;
+ const messageIdentifier = process.env.ERROR_MESSAGE_IDENTIFIER;
+
+ // Escape special characters in the message identifier for safer comparisons
+ const escapedMessageIdentifier = messageIdentifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+
+ const message = `❌ **${messageIdentifier}**
+
+ According to our GitFlow workflow:
+ - Pull requests to the \`main\` branch are only allowed from \`hotfix/*\` branches
+ - Regular feature development and other changes should target the \`develop\` branch
+
+ 📝 **Action required:** Please update your PR to target the \`develop\` branch instead.
+
+ For more details about our contribution workflow, please refer to our [CONTRIBUTING.md](https://github.com/${owner}/${repo}/blob/main/CONTRIBUTING.md) guide.`;
+
+ // First step: Always apply the label
+ console.log("Adding invalid-branch label to PR");
+ try {
+ await github.rest.issues.addLabels({
+ owner,
+ repo,
+ issue_number,
+ labels: [label]
+ });
+ } catch (e) {
+ // In case label already exists or other error
+ console.log(`Note: Could not add label: ${e.message}`);
+ }
+
+ // Second step: Add comment if it doesn't exist
+ const { data: comments } = await github.rest.issues.listComments({
+ owner,
+ repo,
+ issue_number
+ });
+
+ // Use regex test instead of includes for safer comparison
+ const commentExists = comments.some(comment =>
+ comment.body && new RegExp(escapedMessageIdentifier).test(comment.body)
+ );
+
+ if (!commentExists) {
+ console.log("Adding comment to PR");
+ await github.rest.issues.createComment({
+ owner,
+ repo,
+ issue_number,
+ body: message
+ });
+ } else {
+ console.log("Comment already exists, skipping");
+ }
+
+ # Step 3: If the branch pattern is corrected, remove label and comment
+ - name: Clean up if branch is corrected
+ if: steps.branch_check.outputs.result == 'valid' || steps.branch_check.outputs.result == 'not-main'
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_TOKEN }}
+ script: |
+ const { owner, repo } = context.repo;
+ const issue_number = context.payload.pull_request.number;
+ const label = process.env.LABEL_NAME;
+ const messageIdentifier = process.env.ERROR_MESSAGE_IDENTIFIER;
+
+ // Escape special characters in the message identifier
+ const escapedMessageIdentifier = messageIdentifier.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ const messageRegex = new RegExp(escapedMessageIdentifier);
+
+ try {
+ // Check if the label is present and remove it
+ const { data: labels } = await github.rest.issues.listLabelsOnIssue({
+ owner,
+ repo,
+ issue_number
+ });
+
+ if (labels.some(l => l.name === label)) {
+ console.log("Removing invalid-branch label from PR");
+ await github.rest.issues.removeLabel({
+ owner,
+ repo,
+ issue_number,
+ name: label
+ });
+ } else {
+ console.log("No label to remove");
+ }
+
+ // Check existing comments and remove any invalid branch comments
+ const { data: comments } = await github.rest.issues.listComments({
+ owner,
+ repo,
+ issue_number
+ });
+
+ // Find and delete any invalid branch comment
+ for (const comment of comments) {
+ // Use regex test instead of includes for safer comparison
+ if (comment.body && messageRegex.test(comment.body)) {
+ console.log(`Deleting comment ID: ${comment.id}`);
+ await github.rest.issues.deleteComment({
+ owner,
+ repo,
+ comment_id: comment.id
+ });
+ }
+ }
+ } catch (error) {
+ console.log(`Error in cleanup: ${error}`);
+ }
\ No newline at end of file
diff --git a/.github/workflows/GitFlow_Create-Release-Branch-and-PR.yaml b/.github/workflows/GitFlow_Create-Release-Branch-and-PR.yaml
new file mode 100644
index 00000000..36ed1c39
--- /dev/null
+++ b/.github/workflows/GitFlow_Create-Release-Branch-and-PR.yaml
@@ -0,0 +1,71 @@
+# This workflow implements the GitFlow release creation process:
+# - Creates a new release branch from develop
+# - Increments version according to semantic versioning
+# - Creates a pull request targeting main branch
+# - This enables final testing before the actual release is created
+
+name: GitFlow | Create Release Branch and PR
+
+on:
+ # Manual trigger with version selection
+ workflow_dispatch:
+ inputs:
+ version:
+ type: choice
+ default: "Minor"
+ description: Select next release type
+ options:
+ - Patch # For bug fixes (x.y.Z)
+ - Minor # For new features (x.Y.z)
+ - Major # For breaking changes (X.y.z)
+ required: true
+
+jobs:
+ create-release:
+ runs-on: ubuntu-latest
+ steps:
+ # Step 1: Calculate the next version number based on the selected increment type
+ - name: Auto Increment Semver Action
+ uses: MCKanpolat/auto-semver-action@5003b8d37f4b03d95f15303ea10242cbf7c13141 # 2
+ id: versioning
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ incrementPerCommit: false
+ releaseType: ${{ github.event.inputs.version }}
+
+ # Step 2: Checkout the develop branch which contains all approved features
+ - name: Checkout code
+ uses: actions/checkout@v4.2.2
+ with:
+ ref: develop # Always create releases from develop branch
+ fetch-depth: 0
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ # Step 3: Create a new release branch following GitFlow naming convention
+ - name: Create release branch
+ run: |
+ # Configure Git with GitHub Actions identity
+ git config --global user.name "GitHub Actions"
+ git config --global user.email "actions@github.com"
+
+ # Create a new branch with the pattern release/X.Y.Z
+ git checkout -b release/${{ steps.versioning.outputs.version }}
+
+ # Push the branch to remote repository
+ git push origin release/${{ steps.versioning.outputs.version }}
+ echo "Release Branch: release/${{ steps.versioning.outputs.version }}"
+
+ # Step 4: Create a pull request from release branch to main
+ - name: Create Pull Request with GitHub CLI
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ # Use GitHub CLI to create a properly formatted Pull Request
+ gh pr create \
+ --base main \
+ --head release/${{ steps.versioning.outputs.version }} \
+ --title "Release ${{ steps.versioning.outputs.version }}" \
+ --label "release" \
+ --body "# Release ${{ steps.versioning.outputs.version }}
+
+ This PR is automatically created to perform the final tests and validations before the release is created."
\ No newline at end of file
diff --git a/.github/workflows/GitFlow_Make-Release-and-Sync-to-Dev.yml b/.github/workflows/GitFlow_Make-Release-and-Sync-to-Dev.yml
new file mode 100644
index 00000000..b14710c1
--- /dev/null
+++ b/.github/workflows/GitFlow_Make-Release-and-Sync-to-Dev.yml
@@ -0,0 +1,150 @@
+# This workflow completes the GitFlow release process:
+# - Triggers automatically when a PR from release/* or hotfix/* to main is merged
+# - Extracts version number from branch name
+# - Builds stable release artifacts (not nightly builds)
+# - Creates GitHub release with download stats
+# - Synchronizes develop branch with main to maintain GitFlow integrity
+
+name: GitFlow | Make Release and resync to develop
+
+on:
+ # Trigger when PRs to main are closed (merged or not)
+ pull_request:
+ types: [closed]
+ branches:
+ - main
+
+permissions:
+ contents: write
+ pull-requests: read
+
+jobs:
+ build:
+ name: Create Release
+ # Run only when PR is merged (not just closed) and source branch is release/* or hotfix/*
+ if: github.event.pull_request.merged == true && (startsWith(github.event.pull_request.head.ref, 'release/') || startsWith(github.event.pull_request.head.ref, 'hotfix/'))
+ runs-on: windows-latest
+ steps:
+ # Step 1: Checkout the code from the main branch after merge
+ - name: Checkout code
+ uses: actions/checkout@v4.2.2
+ with:
+ lfs: "true"
+ fetch-depth: 0
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ # Step 2: Extract version from branch name and calculate build number
+ - name: Get final Release Version
+ id: release_version
+ shell: bash
+ run: |
+ # Extract version from branch name if it's a release branch
+ if [[ "${{ github.event.pull_request.head.ref }}" =~ ^release/ ]]; then
+ VERSION=$(echo "${{ github.event.pull_request.head.ref }}" | sed -E 's/^release\///')
+ echo "Version extracted from release branch: $VERSION"
+ else
+ # Fetch the latest stable version for hotfix
+ LATEST_TAG=$(git tag -l --sort=-v:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
+ echo "Latest stable version: $LATEST_TAG"
+ # Calculate the new hotfix version by incrementing patch number
+ IFS='.' read -r -a version_parts <<< "${LATEST_TAG/v/}"
+ PATCH=$((version_parts[2] + 1))
+ VERSION="${version_parts[0]}.${version_parts[1]}.$PATCH"
+ echo "Version generated for hotfix: $VERSION"
+ fi
+ # Get the commit count and apply modulo 65535 (MSI version component limit)
+ commit_count=$(git rev-list --count HEAD)
+ commit_count_mod=$((commit_count % 65535))
+ NEW_VERSION="$VERSION.$commit_count_mod"
+ echo "Final version: $NEW_VERSION"
+ echo "newversion=$NEW_VERSION" >> $GITHUB_OUTPUT
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
+
+ # Step 3: Build all project artifacts for the stable release
+ - name: Build project
+ id: build_project
+ shell: powershell
+ run: |
+ # Download and install Microsoft Deployment Toolkit
+ echo "### Get MDT from Microsoft ###"
+ wget https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi -UseBasicParsing -OutFile .\MicrosoftDeploymentToolkit_x64.msi
+ Start-Process .\MicrosoftDeploymentToolkit_x64.msi -ArgumentList "/quiet /norestart" -Wait
+
+ # Extract ServiceUI for elevated notifications
+ echo "### Copy ServiceUI.exe x64 to 'Sources\Winget-AutoUpdate' folder ###"
+ Copy-Item -Path "C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64\ServiceUI.exe" -Destination ".\Sources\Winget-AutoUpdate\ServiceUI.exe" -Force
+ Get-Item .\Sources\Winget-AutoUpdate\*
+
+ # Install WiX tools for MSI creation
+ echo "### Install WiX ###"
+ dotnet new console
+ dotnet tool install --global wix --version 5.0.1
+ wix extension add WixToolset.UI.wixext/5.0.1 -g
+ wix extension add WixToolset.Util.wixext/5.0.1 -g
+
+ # Build MSI package with STABLE flag
+ echo "### Create WAU msi ###"
+ cd .\Sources\Wix\
+ wix build -src build.wxs -ext WixToolset.Util.wixext -ext WixToolset.UI.wixext -out ..\..\WAU.msi -arch x64 -d Version=${{ steps.release_version.outputs.newversion }} -d NextSemVer=${{ steps.release_version.outputs.newversion }} -d Comment="STABLE" -d PreRelease=0
+ cd ..\..
+ Get-Item .\WAU.msi
+
+ # Calculate MSI file hash for verification
+ echo "### Get MSI file SHA ###"
+ $MsiSHA = (Get-FileHash .\WAU.msi).hash
+ echo " - WAU.msi SHA256: $MsiSHA"
+ echo "msi_sha=$MsiSHA" >> $env:GITHUB_OUTPUT
+
+ # Package ADMX policy templates
+ echo "### Zip ADMX ###"
+ Compress-Archive -Path .\Sources\Policies\ADMX -DestinationPath .\WAU_ADMX.zip -Force
+ Get-Item .\*.zip
+
+ # Calculate ADMX package hash for verification
+ echo "### Get ADMX zip SHA ###"
+ $ADMXSHA = (Get-FileHash .\WAU_ADMX.zip).hash
+ echo " - WAU_ADMX.zip SHA256: $ADMXSHA"
+ echo "admx_sha=$ADMXSHA" >> $env:GITHUB_OUTPUT
+
+ # Create installation counter file for tracking installs
+ echo "### Create install counter file ###"
+ echo "Install counter file." > WAU_InstallCounter
+
+ # Step 4: Create stable GitHub release with all artifacts
+ - name: Create release
+ uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1.16.0
+ with:
+ tag: v${{ steps.release_version.outputs.version }}
+ prerelease: false # This is a stable release
+ generateReleaseNotes: true
+ name: WAU ${{ steps.release_version.outputs.version }}
+ artifacts: "WAU.msi,WAU_ADMX.zip,WAU_InstallCounter"
+ body: |
+ ## Files
+ |Files|Hash (SHA256)|Downloads|
+ |---|---|---|
+ |[WAU.msi](https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v${{ steps.release_version.outputs.version }}/WAU.msi) (x64)|`${{ steps.build_project.outputs.msi_sha }}`||
+ |[WAU_ADMX.zip](https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v${{ steps.release_version.outputs.version }}/WAU_ADMX.zip)|`${{ steps.build_project.outputs.admx_sha }}`||
+
+ 
+
+ # Step 5: Configure Git for merge back to develop
+ - name: Configure Git
+ shell: bash
+ run: |
+ git config --global user.name "GitHub Actions"
+ git config --global user.email "actions@github.com"
+
+ # Step 6: Sync develop with main to ensure all release changes are in the develop branch
+ - name: Sync develop with main
+ shell: bash
+ run: |
+ # Checkout develop branch
+ git checkout develop
+ git pull origin develop
+
+ # Merge main into develop with no fast-forward to preserve history
+ git merge --no-ff origin/main -m "Merge main into develop after the creation of release v${{ steps.release_version.outputs.version }}"
+
+ # Push changes to develop branch
+ git push origin develop
\ No newline at end of file
diff --git a/.github/workflows/GitFlow_Nightly-builds.yml b/.github/workflows/GitFlow_Nightly-builds.yml
new file mode 100644
index 00000000..1ed439a7
--- /dev/null
+++ b/.github/workflows/GitFlow_Nightly-builds.yml
@@ -0,0 +1,174 @@
+# This workflow creates nightly builds from the develop branch:
+# - Checks for merged PRs since the last tag
+# - Creates a pre-release version if changes are detected
+# - Builds and packages the software
+# - Creates GitHub release with artifacts and download counters
+
+name: GitFlow | Nightly Builds
+
+on:
+ # Automated nightly builds at midnight
+ schedule:
+ - cron: "0 0 * * *"
+ # Allow manual triggering for testing
+ workflow_dispatch:
+
+permissions:
+ contents: write
+
+jobs:
+ build:
+ name: Create Nightly Build
+ runs-on: windows-latest
+ steps:
+ # Step 1: Checkout the develop branch for nightly builds
+ - name: Checkout code
+ uses: actions/checkout@v4
+ with:
+ lfs: "true"
+ fetch-depth: 0
+ # Always checkout develop for nightly builds
+ ref: develop
+
+ # Step 2: Verify if a new build is required by checking for merged PRs since last tag
+ - name: Check for merged PRs since last tag
+ id: check_prs
+ shell: powershell
+ run: |
+ # Find the latest tag of any type
+ $LATEST_TAG = git tag --sort=-v:refname | Select-Object -First 1
+ Write-Host "Latest tag: $LATEST_TAG"
+
+ # Get merged PRs since last tag using Git directly
+ $MERGED_PRS = git log --merges --grep="Merge pull request" --oneline "$LATEST_TAG..develop"
+
+ # If merged PRs exist, set BUILD_NEEDED and determine release type
+ if ($MERGED_PRS) {
+ Write-Host "Found PRs merged to develop since latest tag:"
+ Write-Host $MERGED_PRS
+ echo "BUILD_NEEDED=true" >> $env:GITHUB_OUTPUT
+
+ # If latest tag is already a pre-release, create another pre-release
+ # Otherwise create a pre-minor release
+ if ($LATEST_TAG -like "*-*") {
+ echo "RELEASE_TYPE=prerelease" >> $env:GITHUB_OUTPUT
+ }
+ else {
+ echo "RELEASE_TYPE=preminor" >> $env:GITHUB_OUTPUT
+ }
+ Write-Host "Next release: $($LATEST_TAG -like "*-*" ? "prerelease" : "preminor")"
+ } else {
+ # If no merged PRs, skip building
+ Write-Host "No PRs merged to develop since latest tag. Skipping build."
+ echo "BUILD_NEEDED=false" >> $env:GITHUB_OUTPUT
+ }
+
+ # Step 3: Generate new semantic version number
+ - name: Auto Increment Semver Action
+ uses: MCKanpolat/auto-semver-action@5003b8d37f4b03d95f15303ea10242cbf7c13141 # 2
+ if: steps.check_prs.outputs.BUILD_NEEDED == 'true'
+ id: versioning
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ incrementPerCommit: false
+ releaseType: ${{ steps.check_prs.outputs.RELEASE_TYPE }}
+
+ # Step 4: Format version numbers for different purposes (SemVer, MSI version)
+ - name: Format Semver (and MSI version)
+ if: steps.check_prs.outputs.BUILD_NEEDED == 'true'
+ id: format_version
+ shell: powershell
+ run: |
+ # Get version from previous step
+ $NextSemver = "${{ steps.versioning.outputs.version }}"
+
+ # Create MSI-compatible version (x.y.z.build)
+ $commit_count = (git rev-list --count HEAD)
+ $commit_count_mod = $commit_count % 65535 # MSI has a version limit
+ $MsiBase = $NextSemver.Split("-")[0] # Remove prerelease segment
+ $MsiVersion = "$MsiBase.$commit_count_mod"
+
+ # Format the release name
+ $ReleaseName = "WAU $NextSemver [Nightly Build]"
+
+ # Output all version information
+ echo "MSI version: $MsiVersion"
+ echo "Semver created: $NextSemver"
+ echo "Release name: $ReleaseName"
+ echo "MsiVersion=$MsiVersion" >> $env:GITHUB_OUTPUT
+ echo "NextSemVer=$NextSemver" >> $env:GITHUB_OUTPUT
+ echo "ReleaseName=$ReleaseName" >> $env:GITHUB_OUTPUT
+
+ # Step 5: Build the project and generate artifacts
+ - name: Build project
+ if: steps.check_prs.outputs.BUILD_NEEDED == 'true'
+ id: build_project
+ shell: powershell
+ run: |
+ # Download and install Microsoft Deployment Toolkit
+ echo "### Get MDT from Microsoft ###"
+ wget https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi -UseBasicParsing -OutFile .\MicrosoftDeploymentToolkit_x64.msi
+ Start-Process .\MicrosoftDeploymentToolkit_x64.msi -ArgumentList "/quiet /norestart" -Wait
+
+ # Extract ServiceUI for elevated notifications
+ echo "### Copy ServiceUI.exe x64 to 'Sources\Winget-AutoUpdate' folder ###"
+ Copy-Item -Path "C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64\ServiceUI.exe" -Destination ".\Sources\Winget-AutoUpdate\ServiceUI.exe" -Force
+ Get-Item .\Sources\Winget-AutoUpdate\*
+
+ # Install WiX tools for MSI creation
+ echo "### Install WiX ###"
+ dotnet new console
+ dotnet tool install --global wix --version 5.0.1
+ wix extension add WixToolset.UI.wixext/5.0.1 -g
+ wix extension add WixToolset.Util.wixext/5.0.1 -g
+
+ # Build MSI package with version information
+ echo "### Create WAU MSI ###"
+ cd .\Sources\Wix\
+ wix build -src build.wxs -ext WixToolset.Util.wixext -ext WixToolset.UI.wixext -out ..\..\WAU.msi -arch x64 -d Version=${{ steps.format_version.outputs.MsiVersion }} -d NextSemVer=${{ steps.format_version.outputs.NextSemVer }} -d Comment="${{ steps.format_version.outputs.ReleaseName }}" -d PreRelease=1
+ cd ..\..
+ Get-Item .\WAU.msi
+
+ # Calculate MSI file hash for verification
+ echo "### Get MSI file SHA ###"
+ $MsiSHA = (Get-FileHash .\WAU.msi).hash
+ echo " - WAU.msi SHA256: $MsiSHA"
+ echo "msi_sha=$MsiSHA" >> $env:GITHUB_OUTPUT
+
+ # Package ADMX policy templates
+ echo "### Zip ADMX ###"
+ Compress-Archive -Path .\Sources\Policies\ADMX -DestinationPath .\WAU_ADMX.zip -Force
+ Get-Item .\*.zip
+
+ # Calculate ADMX package hash for verification
+ echo "### Get ADMX zip SHA ###"
+ $ADMXSHA = (Get-FileHash .\WAU_ADMX.zip).hash
+ echo " - WAU_ADMX.zip SHA256: $ADMXSHA"
+ echo "admx_sha=$ADMXSHA" >> $env:GITHUB_OUTPUT
+
+ # Create installation counter file for tracking installs
+ echo "### Create install counter file ###"
+ echo "Install counter file." > WAU_InstallCounter
+
+ # Step 6: Create GitHub release with all artifacts
+ - name: Create release
+ uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1.16.0
+ if: steps.check_prs.outputs.BUILD_NEEDED == 'true'
+ with:
+ tag: v${{ steps.format_version.outputs.NextSemVer }}
+ prerelease: true
+ generateReleaseNotes: true
+ name: ${{ steps.format_version.outputs.ReleaseName }}
+ artifacts: "WAU.msi,WAU_ADMX.zip,WAU_InstallCounter"
+ body: |
+ This is an **automated nightly build** created from the latest changes in the develop branch.
+
+ ⚠️ **Warning**: This build may contain unstable features and is intended for testing purposes only.
+
+ ## Files
+ |Files|Hash (SHA256)|Downloads|
+ |---|---|---|
+ |[WAU.msi](https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v${{ steps.format_version.outputs.NextSemVer }}/WAU.msi) (x64)|`${{ steps.build_project.outputs.msi_sha }}`||
+ |[WAU_ADMX.zip](https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v${{ steps.format_version.outputs.NextSemVer }}/WAU_ADMX.zip)|`${{ steps.build_project.outputs.admx_sha }}`||
+
+ 
\ No newline at end of file
diff --git a/.github/workflows/WAU-ReleaseBuilder.yml b/.github/workflows/WAU-ReleaseBuilder.yml
deleted file mode 100644
index 09a37b1c..00000000
--- a/.github/workflows/WAU-ReleaseBuilder.yml
+++ /dev/null
@@ -1,162 +0,0 @@
----
-name: WAU - Release builder
-
-on:
- # To trigger nightly release (Auto)
- schedule:
- - cron: "0 0 * * *"
- # To trigger stable release
- workflow_dispatch:
- inputs:
- version:
- type: choice
- default: "Minor"
- description: Select next release type
- options:
- - Patch
- - Minor
- - Major
- required: true
- pre-release:
- type: boolean
- description: Set as Pre-release version
-
-permissions:
- contents: write
-
-jobs:
- build:
- name: Create Release
- runs-on: windows-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v4
- with:
- lfs: "true"
- fetch-depth: 0
- # Checkout develop for scheduled builds, main for manual releases
- ref: ${{ github.event_name == 'schedule' && 'develop' || 'main' }}
-
- - name: Manually OR Scheduled. If Scheduled, check if release is necessary
- run: |
- if ("${{ github.event_name }}" -eq "schedule") {
- echo "Latest tag:"
- git log --tags --pretty="%ci - %h - %s %d" -n 1
- $LATEST_TAG_DATE = git log --tags -n 1 --pretty="%ct"
- echo $LATEST_TAG_DATE
-
- echo "Latest merge:"
- git log --merges --pretty="%ci - %h - %s %d" -n 1
- $LATEST_MERGE_DATE = git log --merges -n 1 --pretty="%ct"
- echo $LATEST_MERGE_DATE
-
- if ( $LATEST_MERGE_DATE -gt $LATEST_TAG_DATE ) {
- echo "Scheduled request. Latest tag is older than latest merge. Nightly prerelease will be created."
- echo "ReleaseType=Prerelease" >> $env:GITHUB_ENV
- }
- else {
- echo "Scheduled request. Latest tag is not older than latest merge. No new Nightly release needed."
- echo "ReleaseType=No" >> $env:GITHUB_ENV
- }
- }
- else {
- echo "Manual request. Release will be created."
- echo "ReleaseType=Release" >> $env:GITHUB_ENV
- }
-
- - name: Auto Increment Semver Action
- uses: MCKanpolat/auto-semver-action@5003b8d37f4b03d95f15303ea10242cbf7c13141 # 2
- if: env.ReleaseType != 'No'
- id: versioning
- with:
- github_token: ${{ secrets.GITHUB_TOKEN }}
- incrementPerCommit: false
- releaseType: Pre${{ github.event.inputs.version || 'patch'}} # Using Prepatch by default
-
- - name: Format Semver (and msi version)
- if: env.ReleaseType != 'No'
- # Remove "-0" for stable release and replace by "-n" for Nightlies
- run: |
- $NextAutoSemver = "${{ steps.versioning.outputs.version }}"
- if ("${{ env.ReleaseType }}" -eq "Release") {
- $MsiVersion = $NextAutoSemver.Split("-")[0]
- $NextSemver = $NextAutoSemver.Split("-")[0]
- $ReleaseName = "WAU " + $NextSemver
- $Prerelease = 0
- }
- else {
- $MsiVersion = $NextAutoSemver.Split("-")[0]
- $NextSemver = $NextAutoSemver.Replace("-0","-n")
- $ReleaseName = "WAU " + $NextSemver + " [Nightly Build]"
- $Prerelease = 1
- }
- echo "MSI version: $MsiVersion"
- echo "Semver created: $NextSemver"
- echo "Prerelease: $Prerelease"
- echo "Release name: $ReleaseName"
- echo "MsiVersion=$MsiVersion" >> $env:GITHUB_ENV
- echo "NextSemVer=$NextSemVer" >> $env:GITHUB_ENV
- echo "Prerelease=$Prerelease" >> $env:GITHUB_ENV
- echo "ReleaseName=$ReleaseName" >> $env:GITHUB_ENV
-
- - name: Build project
- if: env.ReleaseType != 'No'
- shell: powershell
- run: |
- echo "### Get MDT from Microsoft ###"
- wget https://download.microsoft.com/download/3/3/9/339BE62D-B4B8-4956-B58D-73C4685FC492/MicrosoftDeploymentToolkit_x64.msi -UseBasicParsing -OutFile .\MicrosoftDeploymentToolkit_x64.msi
- Start-Process .\MicrosoftDeploymentToolkit_x64.msi -ArgumentList "/quiet /norestart" -Wait
-
- echo "### Copy ServiceUI.exe x64 to 'Sources\Winget-AutoUpdate' folder ###"
- Copy-Item -Path "C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64\ServiceUI.exe" -Destination ".\Sources\Winget-AutoUpdate\ServiceUI.exe" -Force
- Get-Item .\Sources\Winget-AutoUpdate\*
-
- echo "### Install WiX ###"
- dotnet new console
- dotnet tool install --global wix --version 5.0.1
- wix extension add WixToolset.UI.wixext/5.0.1 -g
- wix extension add WixToolset.Util.wixext/5.0.1 -g
-
- echo "### Create WAU msi ###"
- cd .\Sources\Wix\
- wix build -src build.wxs -ext WixToolset.Util.wixext -ext WixToolset.UI.wixext -out ..\..\WAU.msi -arch x64 -d Version=${{ env.MsiVersion }} -d NextSemVer=${{ env.NextSemVer }} -d Comment="${{ env.ReleaseName }}" -d PreRelease=${{ env.PreRelease }}
- cd ..\..
- Get-Item .\WAU.msi
-
- echo "### Get MSI file SHA ###"
- $MsiSHA = (Get-FileHash .\WAU.msi).hash
- echo " - WAU.msi SHA256: $MsiSHA"
- echo "MSI_SHA=$MsiSHA" >> $env:GITHUB_ENV
-
- echo "### Zip ADMX ###"
- Compress-Archive -Path .\Sources\Policies\ADMX -DestinationPath .\WAU_ADMX.zip -Force
- Get-Item .\*.zip
-
- echo "### Get ADMX zip SHA ###"
- $ADMXSHA = (Get-FileHash .\WAU_ADMX.zip).hash
- echo " - WAU_ADMX.zip SHA256: $ADMXSHA"
- echo "ADMX_SHA=$ADMXSHA" >> $env:GITHUB_ENV
-
- echo "### Create install counter file ###"
- echo "Install counter file." > WAU_InstallCounter
-
- echo "### Download the latest v1 WAU.zip (as v2 updater)"
- wget https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v1.21.13/WAU.zip -UseBasicParsing -OutFile .\WAU.zip
-
- - name: Create release
- uses: ncipollo/release-action@440c8c1cb0ed28b9f43e4d1d670870f059653174 # v1.16.0
- if: env.ReleaseType != 'No'
- with:
- tag: v${{ env.NextSemVer }}
- prerelease: ${{ github.event.inputs.pre-release || true }}
- generateReleaseNotes: true
- name: ${{ env.ReleaseName }}
- artifacts: "WAU.msi,WAU_ADMX.zip,WAU.zip,WAU_InstallCounter"
- body: |
- ## Files
- |Files|Hash (SHA256)|Downloads|
- |---|---|---|
- |[WAU.msi](https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v${{ env.NextSemVer }}/WAU.msi) (x64)|`${{ env.MSI_SHA }}`||
- |[WAU_ADMX.zip](https://github.com/Romanitho/Winget-AutoUpdate/releases/download/v${{ env.NextSemVer }}/WAU_ADMX.zip)|`${{ env.ADMX_SHA }}`||
-
- 
diff --git a/.github/workflows/automerge-dependabot.yml b/.github/workflows/automerge-dependabot.yml
deleted file mode 100644
index cf7bcfc7..00000000
--- a/.github/workflows/automerge-dependabot.yml
+++ /dev/null
@@ -1,21 +0,0 @@
----
-name: "Dependabot Automerge - Action"
-
-on:
- pull_request:
-
-permissions:
- contents: write
- pull-requests: write
-
-jobs:
- auto-merge:
- name: DependabotMerge
- runs-on: ubuntu-latest
- if: ${{ github.actor == 'dependabot[bot]' && github.event_name == 'pull_request'}} # Detect that the PR author is dependabot
- steps:
- - name: Enable auto-merge for Dependabot PRs
- run: gh pr merge --auto --merge "$PR_URL" # Use Github CLI to merge automatically the PR
- env:
- PR_URL: ${{github.event.pull_request.html_url}}
- GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 7006c23c..005f94bb 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,24 +1,45 @@
# Contribution Guide
-Thank you for your interest in contributing to this project! Here are some guidelines and best practices to help you get started.
+Thank you for your interest in contributing to this project!
## Branches
-- **`main`**: Contains the production code and is locked for direct modifications.
+- **`main`**: Contains the production code and is locked for direct commits.
- **`develop`**: Contains the code under development for the next release.
- **`feature/`**: Used to develop new features.
-- **`bugfix/`**: Used to fix bugs.
+- **`hotfix/`**: Used to fix bugs.
## Protection of the `main` Branch
-To ensure the quality and stability of the production code, the `main` branch is protected and locked to prevent direct modifications. All changes must go through a pull request to the `develop` branch.
+To ensure the quality and stability of the production code, contributors should follow these steps:
+- Create a new branch from `develop` for their feature,
+- Once the work is complete, open a pull request
+- Ensure that the pull request has a clear title
+- The pull request must pass all tests and receive approval from reviewers
-Contributors should follow these steps:
-- Create a new branch from `develop` for their feature or bugfix.
-- Once the work is complete, open a pull request to merge their branch into `develop`.
-- Ensure that the pull request has a clear title and description.
-- The pull request must pass all tests and receive a code review before being merged.
+This workflow ensures that the `main` branch remains stable and production-ready.
-This workflow ensures that the `main` branch remains stable and that all changes are properly reviewed and tested before being released.
+## Use Gitflow as much as possible
-Thank you for your contribution!
+
+
+### GitFlow Process
+
+1. **Main Branches**:
+ - `main`: The primary branch containing the official release history.
+ - `develop`: The branch where the latest development changes accumulate.
+
+2. **Branch Types in our Workflow**:
+ - `feature/`: For contributors to develop new features.
+ - `hotfix/`: For contributors to fix critical bugs.
+ - `release/`: Automatically created by GitHub Actions for preparing new production releases (not created directly by contributors).
+
+3. **Pull Request Process for Contributors**:
+ - Each new feature should be developed in a `feature` branch.
+ - A PR should be requested to merge the `feature` branch into `develop`.
+
+4. **Release Creation**:
+ - Once a new release needs to be created, a GitHub Action is manually triggered to create a release branch from the develop branch.
+ - A Pull Request is automatically issued to merge the release branch into the main branch.
+ - Final reviews and validations are performed at this stage.
+ - Merging the release branch into the main branch automatically creates a new release via another GitHub Action.
diff --git a/Sources/Winget-AutoUpdate/Winget-Upgrade.ps1 b/Sources/Winget-AutoUpdate/Winget-Upgrade.ps1
index 0f43d2a8..64a5d0bd 100644
--- a/Sources/Winget-AutoUpdate/Winget-Upgrade.ps1
+++ b/Sources/Winget-AutoUpdate/Winget-Upgrade.ps1
@@ -23,8 +23,7 @@ $Script:ProgressPreference = [System.Management.Automation.ActionPreference]::Si
Write-ToLog "Reading WAUConfig";
$Script:WAUConfig = Get-WAUConfig;
-if ($WAUConfig.WAU_ActivateGPOManagement -eq 1)
-{
+if ($WAUConfig.WAU_ActivateGPOManagement -eq 1) {
Write-ToLog "WAU Policies management Enabled.";
}
#endregion Get settings and Domain/Local Policies (GPO) if activated.
@@ -37,10 +36,8 @@ if ($WAUConfig.WAU_ActivateGPOManagement -eq 1)
[string]$Script:WingetSourceCustom = $DefaultWingetRepoName;
# Defining custom repository for winget tool (only if GPO management is active)
-if ($Script:WAUConfig.WAU_ActivateGPOManagement)
-{
- if ($null -ne $Script:WAUConfig.WAU_WingetSourceCustom)
- {
+if ($Script:WAUConfig.WAU_ActivateGPOManagement) {
+ if ($null -ne $Script:WAUConfig.WAU_WingetSourceCustom) {
$Script:WingetSourceCustom = $Script:WAUConfig.WAU_WingetSourceCustom.Trim();
Write-ToLog "Selecting winget repository named '$($Script:WingetSourceCustom)'";
}
@@ -50,18 +47,16 @@ if ($Script:WAUConfig.WAU_ActivateGPOManagement)
#region Checking execution context
# Check if running account is system or interactive logon System(default) otherwise User
[bool]$Script:IsSystem = [System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem;
-
+
# Check for current session ID (O = system without ServiceUI)
[Int32]$Script:SessionID = [System.Diagnostics.Process]::GetCurrentProcess().SessionId;
#endregion
# Preparation to run in current context
-if ($true -eq $IsSystem)
-{
+if ($true -eq $IsSystem) {
#If log file doesn't exist, force create it
- if (!(Test-Path -Path $LogFile))
- {
+ if (!(Test-Path -Path $LogFile)) {
Write-ToLog "New log file created";
}
@@ -72,19 +67,16 @@ if ($true -eq $IsSystem)
[string]$fp2 = [System.IO.Path]::Combine($IntuneLogsDir, 'WAU-install.log');
# Check if Intune Management Extension Logs folder exists
- if (Test-Path -Path $IntuneLogsDir -PathType Container -ErrorAction SilentlyContinue)
- {
+ if (Test-Path -Path $IntuneLogsDir -PathType Container -ErrorAction SilentlyContinue) {
# Check if symlink WAU-updates.log exists, make symlink (doesn't work under ServiceUI)
- if (!(Test-Path -Path $fp0 -ErrorAction SilentlyContinue))
- {
+ if (!(Test-Path -Path $fp0 -ErrorAction SilentlyContinue)) {
New-Item -Path $fp0 -ItemType SymbolicLink -Value $LogFile -Force -ErrorAction SilentlyContinue | Out-Null;
Write-ToLog "SymLink for 'update' log file created in in $($IntuneLogsDir) folder";
}
# Check if install.log and symlink WAU-install.log exists, make symlink (doesn't work under ServiceUI)
- if ( (Test-Path -Path $fp1 -ErrorAction SilentlyContinue) -and !(Test-Path -Path $fp2 -ErrorAction SilentlyContinue) )
- {
+ if ( (Test-Path -Path $fp1 -ErrorAction SilentlyContinue) -and !(Test-Path -Path $fp2 -ErrorAction SilentlyContinue) ) {
New-Item -Path $fp2 -ItemType SymbolicLink -Value $fp1 -Force -Confirm:$False -ErrorAction SilentlyContinue | Out-Null;
Write-ToLog "SymLink for 'install' log file created in $($IntuneLogsDir) folder"
}
@@ -93,40 +85,34 @@ if ($true -eq $IsSystem)
$UserDirs = Get-ChildItem -Path "C:\Users" -Directory | Where-Object {
($_ -notmatch "Default") -and ($_ -notmatch "Public") -and ($_ -notmatch "All Users") -and ($_ -notmatch "Default User")
}
- foreach ($UserDir in $UserDirs)
- {
+ foreach ($UserDir in $UserDirs) {
# Define user-specific log path and log file
$UserLogPath = "$($UserDir.FullName)\AppData\Roaming\Winget-AutoUpdate\Logs"
$UserLogFile = "$UserLogPath\install_$($UserDir.Name).log"
-
+
# Check if the user's log file exists
- if (Test-Path -Path $UserLogFile -ErrorAction SilentlyContinue)
- {
+ if (Test-Path -Path $UserLogFile -ErrorAction SilentlyContinue) {
# Define the Symlink target
$UserLogLink = "${env:ProgramData}\Microsoft\IntuneManagementExtension\Logs\WAU-user_$($UserDir.Name).log"
-
+
# Create Symlink if it doesn't already exist
- if (!(Test-Path -Path $UserLogLink -ErrorAction SilentlyContinue))
- {
+ if (!(Test-Path -Path $UserLogLink -ErrorAction SilentlyContinue)) {
New-Item -Path $UserLogLink -ItemType SymbolicLink -Value $UserLogFile -Force -ErrorAction SilentlyContinue | Out-Null
Write-ToLog "Created Symlink for user log: $UserLogLink -> $UserLogFile"
}
}
}
}
-
+
#Check if running with session ID 0
- if ($SessionID -eq 0)
- {
+ if ($SessionID -eq 0) {
#Check if ServiceUI exists
[string]$fp3 = [System.IO.Path]::Combine($Script:WorkingDir, 'ServiceUI.exe');
[bool]$ServiceUI = Test-Path $fp3 -PathType Leaf;
- if ($true -eq $ServiceUI)
- {
+ if ($true -eq $ServiceUI) {
#Check if any connected user
$explorerprocesses = @(Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue);
- if ($explorerprocesses.Count -gt 0)
- {
+ if ($explorerprocesses.Count -gt 0) {
Write-ToLog "Rerun WAU in system context with ServiceUI";
Start-Process `
-FilePath $fp3 `
@@ -135,64 +121,53 @@ if ($true -eq $IsSystem)
Wait-Process "ServiceUI" -ErrorAction SilentlyContinue;
Exit 0;
}
- else
- {
+ else {
Write-ToLog -LogMsg "CHECK FOR APP UPDATES (System context)" -IsHeader
}
}
- else
- {
+ else {
Write-ToLog -LogMsg "CHECK FOR APP UPDATES (System context - No ServiceUI)" -IsHeader
}
}
- else
- {
+ else {
Write-ToLog -LogMsg "CHECK FOR APP UPDATES (System context - Connected user)" -IsHeader
}
}
-else
-{
+else {
Write-ToLog -LogMsg "CHECK FOR APP UPDATES (User context)" -IsHeader
}
#region Log running context
-if ($true -eq $IsSystem)
-{
+if ($true -eq $IsSystem) {
# Maximum number of log files to keep. Default is 3. Setting MaxLogFiles to 0 will keep all log files.
$MaxLogFiles = $WAUConfig.WAU_MaxLogFiles
- if ($null -eq $MaxLogFiles)
- {
+ if ($null -eq $MaxLogFiles) {
[int32]$MaxLogFiles = 3;
}
- else
- {
+ else {
[int32]$MaxLogFiles = $MaxLogFiles;
}
# Maximum size of log file.
$MaxLogSize = $WAUConfig.WAU_MaxLogSize;
- if (!$MaxLogSize)
- {
+ if (!$MaxLogSize) {
[int64]$MaxLogSize = [int64]1MB; # in bytes, default is 1 MB = 1048576
}
- else
- {
+ else {
[int64]$MaxLogSize = $MaxLogSize;
}
#LogRotation if System
[bool]$LogRotate = Invoke-LogRotation $LogFile $MaxLogFiles $MaxLogSize;
- if ($false -eq $LogRotate)
- {
+ if ($false -eq $LogRotate) {
Write-ToLog "An Exception occurred during Log Rotation..."
}
}
#endregion Log running context
#region Run Scope Machine function if run as System
-if ($true -eq $IsSystem)
-{
+if ($true -eq $IsSystem) {
Add-ScopeMachine;
}
#endregion Run Scope Machine function if run as System
@@ -200,15 +175,13 @@ if ($true -eq $IsSystem)
#region Get Notif Locale function
[string]$LocaleDisplayName = Get-NotifLocale;
Write-ToLog "Notification Level: $($WAUConfig.WAU_NotificationLevel). Notification Language: $LocaleDisplayName" "Cyan";
-#endregion
+#endregion
#Check network connectivity
-if (Test-Network)
-{
+if (Test-Network) {
#Check prerequisites
- if ($true -eq $IsSystem)
- {
+ if ($true -eq $IsSystem) {
Install-Prerequisites;
}
@@ -216,11 +189,9 @@ if (Test-Network)
[string]$Script:Winget = Get-WingetCmd;
Write-ToLog "Selected winget instance: $($Script:Winget)";
- if ($Script:Winget)
- {
+ if ($Script:Winget) {
- if ($true -eq $IsSystem)
- {
+ if ($true -eq $IsSystem) {
#Get Current Version
$WAUCurrentVersion = $WAUConfig.ProductVersion;
@@ -229,86 +200,67 @@ if (Test-Network)
#Check if WAU update feature is enabled or not if run as System
$WAUDisableAutoUpdate = $WAUConfig.WAU_DisableAutoUpdate;
#If yes then check WAU update if run as System
- if ($WAUDisableAutoUpdate -eq 1)
- {
+ if ($WAUDisableAutoUpdate -eq 1) {
Write-ToLog "WAU AutoUpdate is Disabled." "Gray";
}
- else
- {
+ else {
Write-ToLog "WAU AutoUpdate is Enabled." "Green";
#Get Available Version
$Script:WAUAvailableVersion = Get-WAUAvailableVersion;
#Compare
- if ([version]$WAUAvailableVersion.replace("-n", "") -gt [version]$WAUCurrentVersion.replace("-n", ""))
- {
+ if ([version]$WAUAvailableVersion.replace("-n", "") -gt [version]$WAUCurrentVersion.replace("-n", "")) {
#If new version is available, update it
Write-ToLog "WAU Available version: $WAUAvailableVersion" "Yellow";
Update-WAU;
}
- else
- {
+ else {
Write-ToLog "WAU is up to date." "Green";
}
}
#Delete previous list_/winget_error (if they exist) if run as System
[string]$fp4 = [System.IO.Path]::Combine($Script:WorkingDir, 'logs', 'error.txt');
- if (Test-Path $fp4)
- {
+ if (Test-Path $fp4) {
Remove-Item $fp4 -Force;
}
#Get External ListPath if run as System
- if ($WAUConfig.WAU_ListPath)
- {
+ if ($WAUConfig.WAU_ListPath) {
$ListPathClean = $($WAUConfig.WAU_ListPath.TrimEnd(" ", "\", "/"))
Write-ToLog "WAU uses External Lists from: $ListPathClean"
- if ($ListPathClean -ne "GPO")
- {
+ if ($ListPathClean -ne "GPO") {
$NewList = Test-ListPath $ListPathClean $WAUConfig.WAU_UseWhiteList $WAUConfig.InstallLocation.TrimEnd(" ", "\")
- if ($ReachNoPath)
- {
+ if ($ReachNoPath) {
Write-ToLog "Couldn't reach/find/compare/copy from $ListPathClean..." "Red"
- if ($ListPathClean -notlike "http*")
- {
- if (Test-Path -Path "$ListPathClean" -PathType Leaf)
- {
+ if ($ListPathClean -notlike "http*") {
+ if (Test-Path -Path "$ListPathClean" -PathType Leaf) {
Write-ToLog "PATH must end with a Directory, not a File..." "Red"
}
}
- else
- {
- if ($ListPathClean -match "_apps.txt")
- {
+ else {
+ if ($ListPathClean -match "_apps.txt") {
Write-ToLog "PATH must end with a Directory, not a File..." "Red"
}
}
$Script:ReachNoPath = $False
}
- if ($NewList)
- {
- if ($AlwaysDownloaded)
- {
+ if ($NewList) {
+ if ($AlwaysDownloaded) {
Write-ToLog "List downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))" "Yellow"
}
- else
- {
+ else {
Write-ToLog "Newer List downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))" "Yellow"
}
$Script:AlwaysDownloaded = $False
}
- else
- {
- if ($WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\included_apps.txt"))
- {
+ else {
+ if ($WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\included_apps.txt")) {
Write-ToLog "List (white) is up to date." "Green"
}
- elseif (!$WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\excluded_apps.txt"))
- {
+ elseif (!$WAUConfig.WAU_UseWhiteList -and (Test-Path "$WorkingDir\excluded_apps.txt")) {
Write-ToLog "List (black) is up to date." "Green"
}
- else
- {
+ else {
Write-ToLog "Critical: White/Black List doesn't exist, exiting..." "Red"
New-Item "$WorkingDir\logs\error.txt" -Value "White/Black List doesn't exist" -Force
Exit 1
@@ -318,54 +270,43 @@ if (Test-Network)
}
#Get External ModsPath if run as System
- if ($WAUConfig.WAU_ModsPath)
- {
+ if ($WAUConfig.WAU_ModsPath) {
$ModsPathClean = $($WAUConfig.WAU_ModsPath.TrimEnd(" ", "\", "/"))
Write-ToLog "WAU uses External Mods from: $ModsPathClean"
- if ($WAUConfig.WAU_AzureBlobSASURL)
- {
+ if ($WAUConfig.WAU_AzureBlobSASURL) {
$NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(" ", "\") $WAUConfig.WAU_AzureBlobSASURL.TrimEnd(" ")
}
- else
- {
+ else {
$NewMods, $DeletedMods = Test-ModsPath $ModsPathClean $WAUConfig.InstallLocation.TrimEnd(" ", "\")
}
- if ($ReachNoPath)
- {
+ if ($ReachNoPath) {
Write-ToLog "Couldn't reach/find/compare/copy from $ModsPathClean..." "Red"
$Script:ReachNoPath = $False
}
- if ($NewMods -gt 0)
- {
+ if ($NewMods -gt 0) {
Write-ToLog "$NewMods newer Mods downloaded/copied to local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Yellow"
}
- else
- {
- if (Test-Path "$WorkingDir\mods\*.ps1")
- {
+ else {
+ if (Test-Path "$WorkingDir\mods\*.ps1") {
Write-ToLog "Mods are up to date." "Green"
}
- else
- {
+ else {
Write-ToLog "No Mods are implemented..." "Yellow"
}
}
- if ($DeletedMods -gt 0)
- {
+ if ($DeletedMods -gt 0) {
Write-ToLog "$DeletedMods Mods deleted (not externally managed) from local path: $($WAUConfig.InstallLocation.TrimEnd(" ", "\"))\mods" "Red"
}
}
#Test if _WAU-mods.ps1 exist: Mods for WAU (if Network is active/any Winget is installed/running as SYSTEM)
$Mods = "$WorkingDir\mods"
- if (Test-Path "$Mods\_WAU-mods.ps1")
- {
+ if (Test-Path "$Mods\_WAU-mods.ps1") {
Write-ToLog "Running Mods for WAU..." "Yellow"
& "$Mods\_WAU-mods.ps1"
$ModsExitCode = $LASTEXITCODE
#If _WAU-mods.ps1 has ExitCode 1 - Re-run WAU
- if ($ModsExitCode -eq 1)
- {
+ if ($ModsExitCode -eq 1) {
Write-ToLog "Re-run WAU"
Start-Process powershell -ArgumentList "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -Command `"$WorkingDir\winget-upgrade.ps1`""
Exit
@@ -374,41 +315,33 @@ if (Test-Network)
}
- if ($($WAUConfig.WAU_ListPath) -eq "GPO")
- {
+ if ($($WAUConfig.WAU_ListPath) -eq "GPO") {
$Script:GPOList = $True
}
#Get White or Black list
- if ($WAUConfig.WAU_UseWhiteList -eq 1)
- {
+ if ($WAUConfig.WAU_UseWhiteList -eq 1) {
Write-ToLog "WAU uses White List config"
$toUpdate = Get-IncludedApps
$UseWhiteList = $true
}
- else
- {
+ else {
Write-ToLog "WAU uses Black List config"
$toSkip = Get-ExcludedApps
}
#Fix and count the array if GPO List as ERROR handling!
- if ($GPOList)
- {
- if ($UseWhiteList)
- {
- if (-not $toUpdate)
- {
+ if ($GPOList) {
+ if ($UseWhiteList) {
+ if (-not $toUpdate) {
Write-ToLog "Critical: Whitelist doesn't exist in GPO, exiting..." "Red"
New-Item "$WorkingDir\logs\error.txt" -Value "Whitelist doesn't exist in GPO" -Force
Exit 1
}
foreach ($app in $toUpdate) { Write-ToLog "Include app ${app}" }
}
- else
- {
- if (-not $toSkip)
- {
+ else {
+ if (-not $toSkip) {
Write-ToLog "Critical: Blacklist doesn't exist in GPO, exiting..." "Red"
New-Item "$WorkingDir\logs\error.txt" -Value "Blacklist doesn't exist in GPO" -Force
Exit 1
@@ -422,16 +355,13 @@ if (Test-Network)
$outdated = Get-WingetOutdatedApps -src $Script:WingetSourceCustom;
#If something unusual happened or no update found
- if ($outdated -like "No update found.*")
- {
+ if ($outdated -like "No update found.*") {
Write-ToLog "$outdated" "cyan"
}
#Run only if $outdated is populated!
- else
- {
+ else {
#Log list of app to update
- foreach ($app in $outdated)
- {
+ foreach ($app in $outdated) {
#List available updates
$Log = "-> Available update : $($app.Name). Current version : $($app.Version). Available version : $($app.AvailableVersion)."
$Log | Write-Host
@@ -442,79 +372,64 @@ if (Test-Network)
$Script:InstallOK = 0
#Trick under user context when -BypassListForUsers is used
- if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq 1)
- {
+ if ($IsSystem -eq $false -and $WAUConfig.WAU_BypassListForUsers -eq 1) {
Write-ToLog "Bypass system list in user context is Enabled."
$UseWhiteList = $false
$toSkip = $null
}
#If White List
- if ($UseWhiteList)
- {
+ if ($UseWhiteList) {
#For each app, notify and update
- foreach ($app in $outdated)
- {
+ foreach ($app in $outdated) {
#if current app version is unknown, skip it
- if ($($app.Version) -eq "Unknown")
- {
+ if ($($app.Version) -eq "Unknown") {
Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray"
}
#if app is in "include list", update it
- elseif ($toUpdate -contains $app.Id)
- {
+ elseif ($toUpdate -contains $app.Id) {
Update-App $app
}
#if app with wildcard is in "include list", update it
- elseif ($toUpdate | Where-Object { $app.Id -like $_ })
- {
+ elseif ($toUpdate | Where-Object { $app.Id -like $_ }) {
Write-ToLog "$($app.Name) is wildcard in the include list."
Update-App $app
}
#else, skip it
- else
- {
+ else {
Write-ToLog "$($app.Name) : Skipped upgrade because it is not in the included app list" "Gray"
}
}
}
#If Black List or default
- else
- {
+ else {
#For each app, notify and update
- foreach ($app in $outdated)
- {
+ foreach ($app in $outdated) {
#if current app version is unknown, skip it
- if ($($app.Version) -eq "Unknown")
- {
+ if ($($app.Version) -eq "Unknown") {
Write-ToLog "$($app.Name) : Skipped upgrade because current version is 'Unknown'" "Gray"
}
#if app is in "excluded list", skip it
- elseif ($toSkip -contains $app.Id)
- {
+ elseif ($toSkip -contains $app.Id) {
Write-ToLog "$($app.Name) : Skipped upgrade because it is in the excluded app list" "Gray"
}
#if app with wildcard is in "excluded list", skip it
- elseif ($toSkip | Where-Object { $app.Id -like $_ })
- {
+ elseif ($toSkip | Where-Object { $app.Id -like $_ }) {
Write-ToLog "$($app.Name) : Skipped upgrade because it is *wildcard* in the excluded app list" "Gray"
}
# else, update it
- else
- {
+ else {
Update-App $app
}
}
}
- if ($InstallOK -gt 0)
- {
+ if ($InstallOK -gt 0) {
Write-ToLog "$InstallOK apps updated ! No more update." "Green"
}
}
- if ($InstallOK -eq 0 -or !$InstallOK)
- {
+ if ($InstallOK -eq 0 -or !$InstallOK) {
Write-ToLog "No new update." "Green"
}
@@ -527,18 +442,15 @@ if (Test-Network)
}
#Check if user context is activated during system run
- if ($IsSystem -and ($WAUConfig.WAU_UserContext -eq 1))
- {
+ if ($IsSystem -and ($WAUConfig.WAU_UserContext -eq 1)) {
$UserContextTask = Get-ScheduledTask -TaskName 'Winget-AutoUpdate-UserContext' -ErrorAction SilentlyContinue
$explorerprocesses = @(Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue)
- If ($explorerprocesses.Count -eq 0)
- {
+ If ($explorerprocesses.Count -eq 0) {
Write-ToLog "No explorer process found / Nobody interactively logged on..."
}
- Else
- {
+ Else {
#Get Winget system apps to escape them before running user context
Write-ToLog "User logged on, get a list of installed Winget apps in System context..."
Get-WingetSystemApps -src $Script:WingetSourceCustom;
@@ -550,8 +462,7 @@ if (Test-Network)
}
}
}
- else
- {
+ else {
Write-ToLog "Critical: Winget not installed or detected, exiting..." "red"
New-Item "$WorkingDir\logs\error.txt" -Value "Winget not installed or detected" -Force
Write-ToLog "End of process!" "Cyan"