Include workflows in write-all when feature flag is enabled

The write-all permission level should include workflows:write when the
AllowWorkflowsPermission feature flag is enabled, matching the behavior
of other gated permissions like copilot-requests. Previously workflows
was unconditionally excluded from write-all. This aligns with the ADR
decision that write-all means permissive access.
This commit is contained in:
Salman Muin Kayser Chishti
2026-04-11 08:49:41 +01:00
parent 273538003e
commit 18f53d3c9e
3 changed files with 11 additions and 7 deletions
@@ -32,7 +32,7 @@ namespace GitHub.Actions.WorkflowParser.Conversion
return; return;
} }
var effectiveMax = explicitMax ?? CreatePermissionsFromPolicy(context, permissionsPolicy, includeIdToken: isTrusted, includeModels: context.GetFeatures().AllowModelsPermission); var effectiveMax = explicitMax ?? CreatePermissionsFromPolicy(context, permissionsPolicy, includeIdToken: isTrusted, includeModels: context.GetFeatures().AllowModelsPermission, includeWorkflows: context.GetFeatures().AllowWorkflowsPermission);
if (requested.ViolatesMaxPermissions(effectiveMax, out var permissionLevelViolations)) if (requested.ViolatesMaxPermissions(effectiveMax, out var permissionLevelViolations))
{ {
@@ -59,7 +59,8 @@ namespace GitHub.Actions.WorkflowParser.Conversion
TemplateContext context, TemplateContext context,
string permissionsPolicy, string permissionsPolicy,
bool includeIdToken, bool includeIdToken,
bool includeModels) bool includeModels,
bool includeWorkflows)
{ {
switch (permissionsPolicy) switch (permissionsPolicy)
{ {
@@ -70,7 +71,7 @@ namespace GitHub.Actions.WorkflowParser.Conversion
Packages = PermissionLevel.Read, Packages = PermissionLevel.Read,
}; };
case WorkflowConstants.PermissionsPolicy.Write: case WorkflowConstants.PermissionsPolicy.Write:
return new Permissions(PermissionLevel.Write, includeIdToken: includeIdToken, includeAttestations: true, includeModels: includeModels); return new Permissions(PermissionLevel.Write, includeIdToken: includeIdToken, includeAttestations: true, includeModels: includeModels, includeWorkflows: includeWorkflows);
default: default:
throw new ArgumentException($"Unexpected permission policy: '{permissionsPolicy}'"); throw new ArgumentException($"Unexpected permission policy: '{permissionsPolicy}'");
} }
@@ -1877,7 +1877,7 @@ namespace GitHub.Actions.WorkflowParser.Conversion
permissionsStr.AssertUnexpectedValue(permissionsStr.Value); permissionsStr.AssertUnexpectedValue(permissionsStr.Value);
break; break;
} }
return new Permissions(permissionLevel, includeIdToken: true, includeAttestations: true, includeModels: context.GetFeatures().AllowModelsPermission); return new Permissions(permissionLevel, includeIdToken: true, includeAttestations: true, includeModels: context.GetFeatures().AllowModelsPermission, includeWorkflows: context.GetFeatures().AllowWorkflowsPermission);
} }
var mapping = token.AssertMapping("permissions"); var mapping = token.AssertMapping("permissions");
+6 -3
View File
@@ -39,7 +39,8 @@ namespace GitHub.Actions.WorkflowParser
PermissionLevel permissionLevel, PermissionLevel permissionLevel,
bool includeIdToken, bool includeIdToken,
bool includeAttestations, bool includeAttestations,
bool includeModels) bool includeModels,
bool includeWorkflows = false)
{ {
Actions = permissionLevel; Actions = permissionLevel;
ArtifactMetadata = permissionLevel; ArtifactMetadata = permissionLevel;
@@ -60,8 +61,10 @@ namespace GitHub.Actions.WorkflowParser
Models = includeModels Models = includeModels
? (permissionLevel == PermissionLevel.Write ? PermissionLevel.Read : permissionLevel) ? (permissionLevel == PermissionLevel.Write ? PermissionLevel.Read : permissionLevel)
: PermissionLevel.NoAccess; : PermissionLevel.NoAccess;
// Workflows is excluded from write-all / read-all; must be explicitly requested // Workflows is write-only, so only grant it when permissionLevel is Write
Workflows = PermissionLevel.NoAccess; Workflows = includeWorkflows && permissionLevel == PermissionLevel.Write
? PermissionLevel.Write
: PermissionLevel.NoAccess;
} }
private static KeyValuePair<string, (PermissionLevel, PermissionLevel)>[] ComparisonKeyMapping(Permissions left, Permissions right) private static KeyValuePair<string, (PermissionLevel, PermissionLevel)>[] ComparisonKeyMapping(Permissions left, Permissions right)