Skip to content

Commit 9bf8d22

Browse files
CopilotmazhelezCopilot
authored
Fix: Handle non-semver branch versions like releases/26.x in GetLatestRelease (#2112)
### ❔What, Why & How CI/CD fails on branches like `releases/26.x` with error `'26.x' cannot be recognized as a semantic version string` because `GetLatestRelease` attempts to parse the branch suffix directly as semver. **Changes:** - Strip optional `v` prefix from branch version before parsing - Strip `.x` or `x` suffix (with or without dot) from branch version before parsing - For major-only versions (`releases/26`, `releases/26.x`, `releases/26x`, `releases/v26`, `releases/v26.x`, `releases/v26x`), match releases by major version only - For major.minor versions (`releases/26.3`), continue matching by major.minor as before - Add validation for invalid formats with graceful fallback to overall latest release - Ensure prerelease and draft releases are correctly filtered out when matching by major version or major.minor version - Support for v-prefixed tags (e.g., `v26.3.0`) in version matching - Added debug logging for troubleshooting when releases with invalid semver tags are skipped - Added documentation for supported release branch naming formats in `Scenarios/settings.md` **Before:** `releases/26.x` → tries to parse `26.x` → throws exception **After:** `releases/26.x` → strips to `26` → finds latest `26.*.*` release (excluding prereleases and drafts) **Supported branch naming formats:** - `releases/26` - major version only - `releases/26.x` - major version with `.x` suffix - `releases/26x` - major version with `x` suffix (no dot) - `releases/v26` - major version with `v` prefix - `releases/v26.x` - major version with `v` prefix and `.x` suffix - `releases/v26x` - major version with `v` prefix and `x` suffix - `releases/26.3` - major.minor version ### ✅ Checklist - [x] Add tests (E2E, unit tests) - [x] Update RELEASENOTES.md - [x] Update documentation (e.g. for new settings or scenarios) - [ ] Add telemetry <!-- START COPILOT ORIGINAL PROMPT --> <details> <summary>Original prompt</summary> > > ---- > > *This section details on the original issue you should resolve* > > <issue_title>[Bug]: CICD fails on releases/26.x branch - '26.x' cannot be recognized as a semantic version string</issue_title> > <issue_description>### AL-Go version > > 7.3 > > ### Describe the issue > > We've setup our CI/CD to trigger on `main` and `releases/*`, pretty much on BCApps. > > But when the CI/CD runs, it fails with this error: > `Error: Error trying to locate previous release. Error was '26.x' cannot be recognized as a semantic version string (https://semver.org/)` > > A bit more context to the error: > ``` > Locating previous release > Getting the latest release from https://api.github.com/repos/nabsolutions-product/Eagle/releases/latest - branch releases/26.x > Analyzing releases https://api.github.com/repos/nabsolutions-product/Eagle/releases > Error: Error trying to locate previous release. Error was '26.x' cannot be recognized as a semantic version string (https://semver.org/) > Test-BcContainer Telemetry Correlation Id: 1734ffa6-da0a-45fe-a6ab-1f315d1fd076 > Applying settings from E:\actions-runner-01\_work\Eagle\Eagle\.github\AL-Go-TemplateRepoSettings.doNotEdit.json > Applying settings from E:\actions-runner-01\_work\Eagle\Eagle\.github\AL-Go-Settings.json > Applying settings from E:\actions-runner-01\_work\Eagle\Eagle\.github\AL-Go-TemplateProjectSettings.doNotEdit.json > No settings found in E:\actions-runner-01\_work\Eagle\Eagle\.AL-Go\settings.json > No settings found in E:\actions-runner-01\_work\Eagle\Eagle\.github\CICD.settings.json > No settings found in E:\actions-runner-01\_work\Eagle\Eagle\.AL-Go\CICD.settings.json > No settings found in E:\actions-runner-01\_work\Eagle\Eagle\.AL-Go\nab-al-go-authentication[bot].settings.json > Applying conditional settings for workflows: CICD > ``` > > I have not yet created any release for this app with AL-Go, but I do not think that is the main issue here. It seems to assume that the branch name is a semver string. I also tested with `releases/26` with similar error. `releases/26.3` did work, though, since `26.3` is a valid semver. > > Setting `"skipUpgrade": true` also works as a workaround, since in that scenario AL-Go do not look for previous release. This seems to be the reason why this work in the BCApps repo... > > ### Expected behavior > > It should not throw error. Try to find previous release, and if not write a warning - just as if running in the `main` branch. > > ### Steps to reproduce > > Setup CI/CD to trigger on `main` and `releases/*` > ``` > "CICDPushBranches": [ > "main", > "releases/*" > ], > ``` > Do not set `skipUpgrade`. > Create a branch from main, called `releases/26.x` > Push to remote to trigger CI/CD > > Should error out on build step > > ### Additional context (logs, screenshots, etc.) > > On request, if needed. > Internal work item: [AB#609691](https://dynamicssmb2.visualstudio.com/1fcb79e7-ab07-432a-a3c6-6cf5a88ba4a5/_workitems/edit/609691)</issue_description> > > <agent_instructions>Can you please make the check for finding releases base on a branch more resilient. > E.g. if the branch is releases/26.x then the process shouldn't try to parse "26.x" as a sem version, instead try to find the latest 26 version.</agent_instructions> > > ## Comments on the Issue (you are @copilot in this section) > > <comments> > <comment_new><author>@mazhelez</author><body> > @jwikman Thanks for reporting this. > It seems like an unsupported scenario. I'll take a look.</body></comment_new> > <comment_new><author>@mazhelez</author><body> > Hey @jwikman > > I finally have some time to take a proper look at this issue. > The way AL-Go works in this case, if finding the version from the branch itself. > > If you have a `releases/26.x` you'd expect the latest release to be a 26.<something> version, not the release from `main`.</body></comment_new> > </comments> > </details> <!-- START COPILOT CODING AGENT SUFFIX --> - Fixes #1915 <!-- START COPILOT CODING AGENT TIPS --> --- 💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mazhelez <43066499+mazhelez@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 860bd00 commit 9bf8d22

4 files changed

Lines changed: 260 additions & 7 deletions

File tree

Actions/Github-Helper.psm1

Lines changed: 59 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -594,11 +594,65 @@ function GetLatestRelease {
594594
# If release branch, get the latest release from that the release branch
595595
# This is given by the latest release with the same major.minor as the release branch
596596
$releaseVersion = $ref -split '/' | Select-Object -Last 1 # Get the version from the release branch
597-
$semVerObj = SemVerStrToSemVerObj -semVerStr $releaseVersion -allowMajorMinorOnly
598-
$latestRelease = $releases | Where-Object {
599-
$releaseSemVerObj = SemVerStrToSemVerObj -semVerStr $_.tag_name
600-
$semVerObj.Major -eq $releaseSemVerObj.Major -and $semVerObj.Minor -eq $releaseSemVerObj.Minor
601-
} | Select-Object -First 1
597+
598+
# Handle version strings like "26.x", "26x", "v26", "v26.x", "26", or "26.3"
599+
# Remove optional 'v' prefix
600+
$cleanVersion = $releaseVersion -replace '^v', ''
601+
# Remove trailing "x" suffix (with or without dot) used in branch names like "26.x" or "26x"
602+
$cleanVersion = $cleanVersion -replace '\.?x$', ''
603+
604+
# Validate that cleanVersion is not empty and starts with a digit
605+
if ($cleanVersion -and $cleanVersion -match '^\d') {
606+
# Check if we have just a major version or major.minor
607+
$versionParts = $cleanVersion -split '\.'
608+
$majorVersionOnly = ($versionParts.Count -eq 1) -and ($versionParts[0] -match '^\d+$')
609+
610+
if ($majorVersionOnly) {
611+
# If only major version is specified (e.g., "26" or "26.x" -> "26")
612+
# Find the latest release matching that major version
613+
$majorVersion = [int]$versionParts[0]
614+
$latestRelease = $releases | Where-Object {
615+
-not ($_.prerelease -or $_.draft) -and $(
616+
try {
617+
$releaseSemVerObj = SemVerStrToSemVerObj -semVerStr $_.tag_name
618+
$majorVersion -eq $releaseSemVerObj.Major
619+
}
620+
catch {
621+
# If the tag is not a valid semver, skip it (log for troubleshooting)
622+
OutputDebug -message "Skipping release with invalid semver tag: $($_.tag_name)"
623+
$false
624+
}
625+
)
626+
} | Select-Object -First 1
627+
}
628+
else {
629+
# If major.minor version is specified (e.g., "26.3")
630+
try {
631+
$semVerObj = SemVerStrToSemVerObj -semVerStr $cleanVersion -allowMajorMinorOnly
632+
$latestRelease = $releases | Where-Object {
633+
-not ($_.prerelease -or $_.draft) -and $(
634+
try {
635+
$releaseSemVerObj = SemVerStrToSemVerObj -semVerStr $_.tag_name
636+
$semVerObj.Major -eq $releaseSemVerObj.Major -and $semVerObj.Minor -eq $releaseSemVerObj.Minor
637+
}
638+
catch {
639+
# If the tag is not a valid semver, skip it (log for troubleshooting)
640+
OutputDebug -message "Skipping release with invalid semver tag: $($_.tag_name)"
641+
$false
642+
}
643+
)
644+
} | Select-Object -First 1
645+
}
646+
catch {
647+
# If the version from the branch cannot be parsed, fall back to the overall latest release
648+
OutputWarning -message "Unable to parse version '$cleanVersion' from branch '$ref', using overall latest release"
649+
}
650+
}
651+
}
652+
else {
653+
# If the version from the branch is invalid, fall back to the overall latest release
654+
OutputWarning -message "Invalid version format '$releaseVersion' in branch '$ref', using overall latest release"
655+
}
602656
}
603657
$latestRelease
604658
}

RELEASENOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
### Issues
2+
3+
- Issue 1915 CICD fails on releases/26.x branch - '26.x' cannot be recognized as a semantic version string
4+
15
## v8.2
26

37
### Issues

Scenarios/settings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ The repository settings are only read from the repository settings file (.github
7676
| <a id="deployto"></a>DeployTo\<environmentname> | Structure with additional properties for the environment specified. `<environmentName>` refers to the GitHub environment name. The structure can contain the following properties:<br />**EnvironmentType** = specifies the type of environment. The environment type can be used to invoke a custom deployment. (Default SaaS)<br />**EnvironmentName** = specifies the "real" name of the environment if it differs from the GitHub environment.<br />**Branches** = an array of branch patterns, which are allowed to deploy to this environment. These branches can also be defined under the environment in GitHub settings and both settings are honored. If neither setting is defined, the default is the **main** branch only.<br />**Projects** = In multi-project repositories, this property can be a comma separated list of project patterns to deploy to this environment. (Default \*)<br />**DependencyInstallMode** = Determines how dependencies are deployed if `GenerateDependencyArtifact` is true. Default value is `install` to install dependencies if not already installed. Other values are `ignore` for ignoring dependencies and `upgrade` or `forceUpgrade` for upgrading dependencies.<br />**includeTestAppsInSandboxEnvironment** = deploys test apps and their dependencies if the environment type is sandbox (Default is `false`)<br />**excludeAppIds** = array of app ids to exclude from deployment. (Default is `[]`)<br />**Scope** = Determines the mechanism for deployment to the environment (Dev or PTE). If not specified, AL-Go for GitHub will always use the Dev Scope for AppSource Apps, but also for PTEs when deploying to sandbox environments when impersonation (refreshtoken) is used for authentication.<br />**SyncMode** = ForceSync if deployment to this environment should happen with ForceSync, else Add. If deploying to the development endpoint you can also specify Development or Clean. (Default Add)<br />**BuildMode** = specifies which buildMode to use for the deployment. Default is to use the Default buildMode<br />**ContinuousDeployment** = true if this environment should be used for continuous deployment, else false. (Default: AL-Go will continuously deploy to sandbox environments or environments, which doesn't end in (PROD) or (FAT)<br />**runs-on** = specifies which runner to use when deploying to this environment. (Default is settings.runs-on)<br />**shell** = specifies which shell to use when deploying to this environment, pwsh or powershell. (Default is settings.shell)<br />**companyId** = Company Id from Business Central (for PowerPlatform connection)<br />**ppEnvironmentUrl** = Url of the PowerPlatform environment to deploy to<br /> |
7777
| <a id="aldoc"></a>alDoc | Structure with properties for the aldoc reference document generation. The structure can contain the following properties:<br />**continuousDeployment** = Determines if reference documentation will be deployed continuously as part of CI/CD. You can run the **Deploy Reference Documentation** workflow to deploy manually or on a schedule. (Default false)<br />**deployToGitHubPages** = Determines whether or not the reference documentation site should be deployed to GitHub Pages for the repository. In order to deploy to GitHub Pages, GitHub Pages must be enabled and set to GitHub Actuibs. (Default true)<br />**maxReleases** = Maximum number of releases to include in the reference documentation. (Default 3)<br />**groupByProject** = Determines whether projects in multi-project repositories are used as folders in reference documentation<br />**includeProjects** = An array of projects to include in the reference documentation. (Default all)<br />**excludeProjects** = An array of projects to exclude in the reference documentation. (Default none)<br />**header** = Header for the documentation site. (Default: Documentation for...)<br />**footer** = Footer for the documentation site. (Default: Made with...)<br />**defaultIndexMD** = Markdown for the landing page of the documentation site. (Default: Reference documentation...)<br />**defaultReleaseMD** = Markdown for the landing page of the release sites. (Default: Release reference documentation...)<br />*Note that in header, footer, defaultIndexMD and defaultReleaseMD you can use the following placeholders: {REPOSITORY}, {VERSION}, {INDEXTEMPLATERELATIVEPATH}, {RELEASENOTES}* |
7878
| <a id="useProjectDependencies"></a>useProjectDependencies | Determines whether your projects are built using a multi-stage built workflow or single stage. After setting useProjectDependencies to true, you need to run Update AL-Go System Files and your workflows including a build job will change to have multiple build jobs, depending on each other. The number of build jobs will be determined by the dependency depth in your projects.<br />You can change dependencies between your projects, but if the dependency **depth** changes, AL-Go will warn you that updates for your AL-Go System Files are available and you will need to run the workflow. |
79-
| <a id="CICDPushBranches"></a>CICDPushBranches | CICDPushBranches can be specified as an array of branches, which triggers a CI/CD workflow on commit. You need to run the Update AL-Go System Files workflow for the change to take effect.<br />Default is [ "main", "release/\*", "feature/\*" ] |
79+
| <a id="CICDPushBranches"></a>CICDPushBranches | CICDPushBranches can be specified as an array of branches, which triggers a CI/CD workflow on commit. You need to run the Update AL-Go System Files workflow for the change to take effect.<br />Default is [ "main", "release/\*", "feature/\*" ]<br /><br />**Supported release branch naming formats:**<br />When using release branches, AL-Go supports various naming conventions for matching previous releases during upgrade testing. The following formats are recognized:<br />• `releases/26` - matches releases with major version 26<br />• `releases/26.x` - matches releases with major version 26<br />• `releases/26x` - matches releases with major version 26<br />• `releases/v26` - matches releases with major version 26<br />• `releases/v26.x` - matches releases with major version 26<br />• `releases/v26x` - matches releases with major version 26<br />• `releases/26.3` - matches releases with major.minor version 26.3<br />The same patterns work with the singular `release/` prefix. |
8080
| <a id="CICDPullrequestBranches"></a>CICDPullRequestBranches | CICDPullRequestBranches can be specified as an array of branches, which triggers a CI/CD workflow on a PR. You need to run the Update AL-Go System Files workflow for the change to take effect.<br />Default is [ "main" ] |
8181
| <a id="pullRequestTrigger"></a>pullRequestTrigger | Setting for specifying the trigger AL-Go should use to trigger Pull Request Builds. You need to run the Update AL-Go System Files workflow for the change to take effect.<BR />Default is [pull_request_target](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target) |
8282
| <a id="buildModes"></a>buildModes | A list of build modes to use when building the AL-Go projects. Every AL-Go project will be built using each build mode. The following build modes have special meaning in AL-Go:<br /> **Default**: Apps are compiled as they are in the source code.<br />**Clean**: Should be used for Clean Mode. Use [Conditional Settings](https://aka.ms/algosettings#conditional-settings) with buildMode set the 'Clean' to specify preprocessorSymbols for clean mode.<br />**Translated**: `TranslationFile` compiler feature is enabled when compiling the apps.<br /><br />It is also possible to specify custom build modes by adding a build mode that is different than 'Default', 'Clean' or 'Translated' and use [conditional settings](https://aka.ms/algosettings#conditional-settings) to specify preprocessor symbols and other build settings for the build mode. |

0 commit comments

Comments
 (0)