Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
fcff18b
Set default values on workflow_dispatch input #1952
jwikman Oct 16, 2025
b68121a
Move workflowInputDefaults setting documentation
jwikman Oct 16, 2025
93b49b7
Hide workflow_dispatch input #1952
jwikman Oct 17, 2025
9934749
Fixes Copilot comments
jwikman Oct 17, 2025
a3ae71b
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 17, 2025
aec01d3
Data type checking fix for PowerShell 5
jwikman Oct 17, 2025
018b008
Enhance ApplyWorkflowInputDefaults to validate choice input with case…
jwikman Oct 17, 2025
79e8844
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 17, 2025
dcc40cb
Merge branch 'main' into w/johwik/1952-Set-default-values-on-workflow…
jwikman Oct 17, 2025
13a6644
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Set-d…
jwikman Oct 17, 2025
1c7bd03
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 17, 2025
28f5697
Remove unnecessary blank lines in ApplyWorkflowInputDefaults function…
jwikman Oct 17, 2025
7be5ec9
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Set-d…
jwikman Oct 17, 2025
1c4b190
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 17, 2025
de397ec
Remove unnecessary blank lines in ApplyWorkflowInputDefaults function…
jwikman Oct 17, 2025
ef398c8
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 17, 2025
8e6d97a
Remove unnecessary blank line in RELEASENOTES.md
jwikman Oct 17, 2025
e2fe4f1
Remove unnecessary blank line in CheckForUpdates.Action.Test.ps1
jwikman Oct 17, 2025
a9ebdd1
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 17, 2025
6b826f2
Consolidate Export-ModuleMember for ReadSettings and SanitizeWorkflow…
jwikman Oct 20, 2025
84f6b53
Move module import to global scope
jwikman Oct 20, 2025
f1ada94
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Oct 20, 2025
ac3720c
Merge branch 'main' into w/johwik/1952-Set-default-values-on-workflow…
jwikman Oct 20, 2025
09dc9b5
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Hide-…
jwikman Nov 5, 2025
2a862c0
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Set-d…
jwikman Nov 5, 2025
ddcc482
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Nov 5, 2025
cada39f
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Set-d…
jwikman Nov 13, 2025
df27829
Rename workflowInputDefaults to workflowDefaultInputs in settings and…
jwikman Nov 13, 2025
3f02f9d
Simplified workflowDefaultInputs setting
jwikman Nov 17, 2025
29b1cd5
Add tests for merging workflowDefaultInputs with duplicate entries
jwikman Nov 17, 2025
2c4bf3c
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Set-d…
jwikman Nov 17, 2025
f1cee93
Reorganize and clarify Workflow Name Sanitization section in settings.md
jwikman Nov 17, 2025
2511b24
Set default values for workflow inputs in RELEASENOTES.md and update …
jwikman Nov 17, 2025
a681ffd
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Nov 18, 2025
474a6fd
Remove duplicate inputs handling from ApplyWorkflowDefaultInputs func…
jwikman Nov 18, 2025
627c802
Hide default values from workflow_dispatch inputs in ApplyWorkflowDef…
jwikman Nov 18, 2025
a5c92b5
Add Context grouping to tests
jwikman Nov 18, 2025
d164158
Add exclusion for mdformat hook to prevent formatting in .github/inst…
jwikman Nov 18, 2025
dd7870b
Add testing instructions for AL-Go repository using Pester framework
jwikman Nov 18, 2025
604c5ce
Add reminder to run tests after changes in testing instructions
jwikman Nov 18, 2025
52e65f4
Refactor ApplyWorkflowDefaultInputs to use regex for matching whitesp…
jwikman Nov 18, 2025
055b133
Implement hiding of default values for workflow inputs in ApplyWorkfl…
jwikman Nov 18, 2025
a8bd32f
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Set-d…
jwikman Nov 18, 2025
cd4e95d
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Nov 18, 2025
32b10d4
Add discussion entry for hiding workflow_dispatch input
jwikman Nov 18, 2025
3b94405
Updates after CR
jwikman Nov 18, 2025
207f133
Merge branch 'w/johwik/1952-Set-default-values-on-workflow_dispatch-i…
jwikman Nov 18, 2025
322bfb8
Refactor ApplyWorkflowDefaultInputs function to improve input hiding …
jwikman Nov 18, 2025
a400606
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Hide-…
jwikman Nov 20, 2025
46adbd0
Remove test instructions for now
jwikman Nov 20, 2025
ee37a84
Merge branch 'main' into w/johwik/1952-Hide-default-values-from-workf…
jwikman Dec 3, 2025
756a85c
Add tests for hiding inputs in CheckForUpdates.Action.Test.ps1
jwikman Dec 3, 2025
2e23e48
Merge remote-tracking branch 'upstream/main' into w/johwik/1952-Hide-…
jwikman Dec 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Actions/.Modules/settings.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,10 @@
},
"value": {
"description": "The default value for the workflow input (can be string, boolean, or number)"
},
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent indentation: Line 754 has improper closing of the "value" property (extra spaces before the closing brace). The line should be:

                    },

instead of:

                                },

This maintains consistent indentation with the surrounding JSON properties.

Suggested change
},
},

Copilot uses AI. Check for mistakes.
"hide": {
"type": "boolean",
"description": "If true, the input is removed from the workflow and the configured value is used directly"
}
},
"required": ["name", "value"]
Expand Down
113 changes: 113 additions & 0 deletions Actions/CheckForUpdates/CheckForUpdates.HelperFunctions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -330,10 +330,36 @@ function ApplyWorkflowDefaultInputs {
return
}

# Helper to convert values to GitHub expression literals
$convertToExpressionLiteral = {
param($value)

if ($value -is [bool]) {
return $value.ToString().ToLower()
}

if ($value -is [int] -or $value -is [long] -or $value -is [System.Int16] -or $value -is [byte] -or $value -is [System.SByte] -or $value -is [System.UInt16] -or $value -is [System.UInt32] -or $value -is [System.UInt64]) {
return $value.ToString()
}

if ($value -is [double] -or $value -is [single] -or $value -is [decimal]) {
return $value.ToString([System.Globalization.CultureInfo]::InvariantCulture)
}

$escapedValue = ($value -as [string]) -replace "'", "''"
return "'$escapedValue'"
}

$inputsToHide = @{}

# Apply defaults to matching inputs
foreach ($default in $repoSettings.workflowDefaultInputs) {
$inputName = $default.name
$defaultValue = $default.value
$hideInput = $false
if ($default['hide']) {
$hideInput = [bool]$default.hide
}
Comment on lines +359 to +362
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent indentation: Lines 359-362 have extra indentation (8 spaces instead of 4). This should be aligned with the surrounding code at the same scope level.

Suggested change
$hideInput = $false
if ($default['hide']) {
$hideInput = [bool]$default.hide
}
$hideInput = $false
if ($default['hide']) {
$hideInput = [bool]$default.hide
}

Copilot uses AI. Check for mistakes.

# Check if this input exists in the workflow
$inputSection = $inputs.Get("$($inputName):/")
Expand Down Expand Up @@ -410,6 +436,22 @@ function ApplyWorkflowDefaultInputs {
throw $validationError
}

if ($hideInput) {
# Store this input to hide it later
$inputsToHide[$inputName] = [pscustomobject]@{
value = $defaultValue
expression = & $convertToExpressionLiteral $defaultValue
}
continue
}
else {
# If hide is false, ensure the input is not in the hide list
# This handles the case where a previous entry had hide=true but a later entry has hide=false
if ($inputsToHide.ContainsKey($inputName)) {
$inputsToHide.Remove($inputName)
}
}

# Convert the default value to the appropriate YAML format
$yamlValue = $defaultValue
if ($defaultValue -is [bool]) {
Expand Down Expand Up @@ -465,11 +507,82 @@ function ApplyWorkflowDefaultInputs {
$inputs.Replace("$($inputName):/", $inputSection.content)
}

# Remove hidden inputs from the inputs section
if ($inputsToHide.Count -gt 0) {
# Collect all inputs to remove with their positions
$inputsToRemove = @()
foreach ($entry in $inputsToHide.GetEnumerator()) {
$name = $entry.Key
$start = 0
$count = 0
# Find the input including all its content (type, default, etc.)
# Use the name with colon to match the full input section
if ($inputs.Find("$($name):", [ref] $start, [ref] $count)) {
$inputsToRemove += [pscustomobject]@{
Name = $name
Start = $start
Count = $count
}
}
else {
OutputWarning "Workflow '$workflowName': Unable to hide input '$name' because it was not found in the workflow file."
}
}

# Remove inputs in reverse order to maintain correct indices
foreach ($item in $inputsToRemove | Sort-Object -Property Start -Descending) {
$inputs.Remove($item.Start, $item.Count)
}
}

# Update the workflow_dispatch section with modified inputs
$workflowDispatch.Replace('inputs:/', $inputs.content)

# Update the on: section with modified workflow_dispatch
$yaml.Replace('on:/workflow_dispatch:/', $workflowDispatch.content)

# Replace all references to hidden inputs with their literal values
if ($inputsToHide.Count -gt 0) {
foreach ($entry in $inputsToHide.GetEnumerator()) {
$inputName = $entry.Key
$expressionValue = $entry.Value.expression
$rawValue = $entry.Value.value

# Replace references in expressions: ${{ github.event.inputs.name }} and ${{ inputs.name }}
# These use the expression literal format (true/false for boolean, unquoted number, 'quoted' string)
# Use regex to match any whitespace variations: ${{inputs.name}}, ${{ inputs.name }}, ${{ inputs.name}}, ${{inputs.name }}
# Replace the entire ${{ ... }} expression with just the value
$pattern = "`\$\{\{\s*github\.event\.inputs\.$inputName\s*\}\}"
$yaml.ReplaceAll($pattern, $expressionValue, $true)
$pattern = "`\$\{\{\s*inputs\.$inputName\s*\}\}"
$yaml.ReplaceAll($pattern, $expressionValue, $true)
Comment on lines +555 to +558
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regex patterns are constructed using unescaped input names ($inputName) when replacing hidden input references, e.g., "${{\sgithub.event.inputs.$inputName\s}}"and"(?<!.)inputs.$inputName\b(?!.)". If an input name contains regex metacharacters (like . * + ? ( ) [ ] |), this can cause overbroad or malformed matches and unintended replacements across the workflow, enabling an attacker who controls workflow input names to tamper with workflow logic. Fix by escaping $inputNamefor regex (e.g., using[Regex]::Escape($inputName)`) before interpolating it into patterns:

$escaped = [Regex]::Escape($inputName)
$pattern1 = "`\$\{\{\s*github\.event\.inputs\.$escaped\s*\}\}"
$pattern2 = "(?<!\.)inputs\.$escaped\b(?!\.)"

Also ensure any other regex constructions using input-derived values apply the same escaping.

Copilot uses AI. Check for mistakes.

# Replace references in if conditions: github.event.inputs.name and inputs.name (without ${{ }})
# github.event.inputs are always strings (user input from UI)
# inputs.* are typed values (boolean/number/string/choice)

# For github.event.inputs.NAME: always use string literal format
# Convert the value to a string literal (always quoted) for comparisons
if ($rawValue -is [bool]) {
$stringValue = $rawValue.ToString().ToLower()
}
else {
$stringValue = $rawValue.ToString().Replace("'", "''")
}
$stringLiteral = "'$stringValue'"
$yaml.ReplaceAll("github.event.inputs.$inputName", $stringLiteral)

# For inputs.NAME: use expression literal format (typed value)
# Replace inputs.NAME but be careful not to match patterns like:
# - needs.inputs.outputs.NAME (where a job is named "inputs")
# - steps.CreateInputs.outputs.NAME (where "inputs" is part of a word)
# Use negative lookbehind (?<!\.) to ensure "inputs" is not preceded by a dot
# Use word boundary \b after inputName to avoid partial matches
# Don't match if followed by a dot (to avoid matching outputs references)
$pattern = "(?<!\.)inputs\.$inputName\b(?!\.)"
Copy link

Copilot AI Dec 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regex pattern "(?<!\.)inputs\.$inputName\b(?!\.)" embeds $inputName without regex escaping. If the input name includes regex metacharacters, it can match unintended substrings (e.g., parts of job/step output references or other content) and replace them with attacker-controlled values, corrupting workflow logic. Fix by escaping the name: "(?<!\.)inputs\.[Regex]::Escape($inputName)\b(?!\.)" or build the pattern using $escaped = [Regex]::Escape($inputName) and then interpolate $escaped.

Suggested change
$pattern = "(?<!\.)inputs\.$inputName\b(?!\.)"
$escapedInputName = [Regex]::Escape($inputName)
$pattern = "(?<!\.)inputs\.$escapedInputName\b(?!\.)"

Copilot uses AI. Check for mistakes.
$yaml.ReplaceAll($pattern, $expressionValue, $true)
}
}
}

function GetWorkflowContentWithChangesFromSettings {
Expand Down
12 changes: 11 additions & 1 deletion Actions/CheckForUpdates/yamlclass.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,21 @@ class Yaml {
$this.Add($line, @($key) + @($content | ForEach-Object { " $_" }))
}

# Replace all occurrences of $from with $to throughout the Yaml content
# Replace all occurrences of $from with $to throughout the Yaml content (literal string replacement)
[void] ReplaceAll([string] $from, [string] $to) {
$this.content = $this.content | ForEach-Object { $_.replace($from, $to) }
}

# Replace all occurrences matching regex pattern with $replacement throughout the Yaml content
[void] ReplaceAll([string] $pattern, [string] $replacement, [bool] $isRegex) {
if ($isRegex) {
$this.content = $this.content | ForEach-Object { $_ -replace $pattern, $replacement }
}
else {
$this.ReplaceAll($pattern, $replacement)
}
}

# Remove lines in Yaml content
[void] Remove([int] $start, [int] $count) {
if ($count -eq 0) {
Expand Down
21 changes: 21 additions & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@

AL-Go telemetry now includes test results so you can more easily see how many AL tests, Page Scripting tests and BCPT tests ran in your workflows across all your repositories. Documentation for this can be found on [this article](https://github.com/microsoft/AL-Go/blob/main/Scenarios/EnablingTelemetry.md) on enabling telemetry.

### Hide workflow inputs

This is an addition to the `workflowDefaultInputs` setting introduced in v8.1. You can now hide specific workflow inputs from the manual workflow form in GitHub Actions.

You can now set `"hide": true` for an input to remove it from the manual workflow form. When an input is hidden, all usages of `github.event.inputs.<name>` or `inputs.<name>` in the workflow file are replaced with the configured value when the "Update AL-Go System Files" workflow runs.

Example configuration:

```json
{
"workflowDefaultInputs": [
{ "name": "directCommit", "value": true },
{ "name": "useGhTokenWorkflow", "value": true, "hide": true }
]
}
```

### Issues & Discussions

- Discussion 1952 Hide workflow_dispatch input

## v8.1

### Custom AL-Go files
Expand Down
2 changes: 1 addition & 1 deletion Scenarios/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ The repository settings are only read from the repository settings file (.github
| <a id="useGitSubmodules"></a>useGitSubmodules | If your repository is using Git Submodules, you can set the `useGitSubmodules` setting to `"true"` or `"recursive"` in order to use these submodules during build workflows. If `useGitSubmodules` is not set, git submodules are not initialized. If the submodules reside in private repositories, you need to define a `gitSubmodulesToken` secret. Read [this](https://aka.ms/algosecrets#gitSubmodulesToken) for more information. |
| <a id="commitOptions"></a>commitOptions | If you want more control over how AL-Go creates pull requests or commits changes to the repository you can define `commitOptions`. It is a structure defining how you want AL-Go to handle automated commits or pull requests coming from AL-Go (e.g. for Update AL-Go System Files). The structure contains the following properties:<br />**messageSuffix** = A string you want to append to the end of commits/pull requests created by AL-Go. This can be useful if you are using the Azure Boards integration (or similar integration) to link commits to work items. <br />`createPullRequest` : A boolean defining whether AL-Go should create a pull request or attempt to push directly in the branch.<br />**pullRequestAutoMerge** = A boolean defining whether you want AL-Go pull requests to be set to auto-complete. This will auto-complete the pull requests once all checks are green and all required reviewers have approved.<br />**pullRequestMergeMethod** = A string defining which merge method to use when auto-merging pull requests. Valid values are "merge" and "squash". Default is "squash".<br />**pullRequestLabels** = A list of labels to add to the pull request. The labels need to be created in the repository before they can be applied.<br />If you want different behavior in different AL-Go workflows you can add the `commitOptions` setting to your [workflow-specific settings files](https://github.com/microsoft/AL-Go/blob/main/Scenarios/settings.md#where-are-the-settings-located). |
| <a id="incrementalBuilds"></a>incrementalBuilds | A structure defining how you want AL-Go to handle incremental builds. When using incremental builds for a build, AL-Go will look for the latest successful CI/CD build, newer than the defined `retentionDays` and only rebuild projects or apps (based on `mode`) which needs to be rebuilt. The structure supports the following properties:<br />**onPush** = Determines whether incremental builds is enabled in CI/CD triggered by a merge/push event. Default is **false**.<br />**onPull_Request** = Determines whether incremental builds is enabled in Pull Requests. Default is **true**.<br />**onSchedule** = Determines whether incremental builds is enabled in CI/CD when running on a schedule. Default is **false**.<br />**retentionDays** = Number of days a successful build is good (and can be used for incremental builds). Default is **30**.<br />**mode** = Specifies the mode for incremental builds. Currently, two values are supported. Use **modifiedProjects** when you want to rebuild all apps in all modified projects and depending projects or **modifiedApps** if you want to rebuild modified apps and all apps with dependencies to this app.<br />**NOTE:** when running incremental builds, it is recommended to also set `workflowConcurrency` for the CI/CD workflow, as defined [here](https://aka.ms/algosettings#workflowConcurrency). |
| <a id="workflowDefaultInputs"></a>workflowDefaultInputs | An array of workflow input default values. This setting allows you to configure default values for workflow_dispatch inputs, making it easier to run workflows manually with consistent settings. Each entry should contain:<br />  **name** = The name of the workflow input<br />  **value** = The default value (can be string, boolean, or number)<br />**Important validation rules:**<br />  • The value type must match the input type defined in the workflow YAML file (boolean, number, string, or choice)<br />  • For choice inputs, the value must be one of the options declared in the workflow<br />  • Choice validation is case-sensitive<br />Type and choice validation is performed when running the "Update AL-Go System Files" workflow to prevent configuration errors.<br />When you run the "Update AL-Go System Files" workflow, these default values will be applied to all workflows that have matching input names.<br />**Usage:** This setting can be used on its own in repository settings to apply defaults to all workflows with matching input names. Alternatively, you can use it within [conditional settings](#conditional-settings) to apply defaults only to specific workflows, branches, or other conditions.<br />**Important:** When multiple conditional settings blocks match and both define `workflowDefaultInputs`, the arrays are merged (all entries are kept). When the defaults are applied to workflows, the last matching entry for each input name wins.<br />**Example:**<br />`"workflowDefaultInputs": [`<br />` { "name": "directCommit", "value": true },`<br />` { "name": "useGhTokenWorkflow", "value": true },`<br />` { "name": "updateVersionNumber", "value": "+0.1" }`<br />`]` |
| <a id="workflowDefaultInputs"></a>workflowDefaultInputs | An array of workflow input default values. This setting allows you to configure default values for workflow_dispatch inputs, making it easier to run workflows manually with consistent settings. Each entry should contain:<br />  **name** = The name of the workflow input<br />  **value** = The default value (can be string, boolean, or number)<br />**Important validation rules:**<br />  • The value type must match the input type defined in the workflow YAML file (boolean, number, string, or choice)<br />  • For choice inputs, the value must be one of the options declared in the workflow<br />  • Choice validation is case-sensitive<br />Type and choice validation is performed when running the "Update AL-Go System Files" workflow to prevent configuration errors.<br />When you run the "Update AL-Go System Files" workflow, these default values will be applied to all workflows that have matching input names.<br />**Usage:** This setting can be used on its own in repository settings to apply defaults to all workflows with matching input names. Alternatively, you can use it within [conditional settings](#conditional-settings) to apply defaults only to specific workflows, branches, or other conditions.<br />  **hide** (optional) = Set to `true` to remove the input from the workflow UI and use the configured value automatically. When hiding an input, all usages of `github.event.inputs.<name>` or `inputs.<name>` are replaced with the configured value when the "Update AL-Go System Files" workflow runs.<br />**Important:** When multiple conditional settings blocks match and both define `workflowDefaultInputs`, the arrays are merged (all entries are kept). When the defaults are applied to workflows, the last matching entry for each input name wins.<br />**Example:**<br />`"workflowDefaultInputs": [`<br />` { "name": "directCommit", "value": true },`<br />` { "name": "useGhTokenWorkflow", "value": true, "hide": true },`<br />` { "name": "updateVersionNumber", "value": "+0.1" }`<br />`]` |

<a id="advanced"></a>

Expand Down
Loading
Loading