1
0
Fork 0
mirror of synced 2026-06-05 08:05:14 +00:00

fix: assumeRole failing from session tag size too large (#1808)

* minor readme fixes and print tags when debugging

* redo changes from #1780

* reworked new tags/priority behavior, add drop tags and retry logic

* minor edits to documentation, README update for clarity

* linting fix
This commit is contained in:
Michael Lehmann 2026-06-01 13:55:23 -07:00 committed by GitHub
commit d6f5dc331b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 142 additions and 133 deletions

View file

@ -168,6 +168,7 @@ detail.
| role-session-name | Defaults to "GitHubActions", but may be changed if required. | No |
| role-skip-session-tagging | Skips session tagging if set. | No |
| transitive-tag-keys | Define a list of transitive tag keys to pass when assuming a role. | No |
| custom-tags | Additional tags to apply to the assumed role session. Must be a JSON object provided as a string. Custom tags are not usable with OIDC or web identity token authentication. | No |
| inline-session-policy | You may further restrict the assumed role policy by defining an inline policy here. | No |
| managed-session-policies | You may further restrict the assumed role policy by specifying a managed policy here. | No |
| output-credentials | When set, outputs fetched credentials as action step output. (Outputs aws-access-key-id, aws-secret-access-key, aws-session-token, aws-account-id, authenticated-arn, and aws-expiration). Defaults to false. | No |
@ -180,6 +181,8 @@ detail.
| allowed-account-ids | A comma-delimited list of expected AWS account IDs. The action will fail if we receive credentials for the wrong account. | No |
| force-skip-oidc | When set, the action will skip using GitHub OIDC provider even if the id-token permission is set. | No |
| action-timeout-s | Global timeout for the action in seconds. If set to a value greater than 0, the action will fail if it takes longer than this time to complete. | No |
| no-proxy | Hosts to skip for the proxy configuration. | No |
| sts-endpoint | Custom STS endpoint URL. Use this to point to an STS-compatible API (e.g. MinIO, LocalStack) instead of the default AWS STS endpoint for the region. | No |
</details>
@ -350,8 +353,7 @@ documentation for `GITHUB_` environment variable definitions][gh-env-vars])
[gh-env-vars]:
https://docs.github.com/en/actions/reference/workflows-and-actions/variables#default-environment-variables
**Protected tags** are always emitted when session tags are used, and cannot be
overridden via `custom-tags`:
**Default tags** are always emitted when session tags are used.
| Key | Value |
| ---------- | ----------------- |
@ -363,21 +365,24 @@ overridden via `custom-tags`:
| Commit | GITHUB_SHA |
| Branch | GITHUB_REF |
**Overrideable tags** are automatically added to the set of default session tags
but may be overridden via `custom-tags`. AWS has a maximum limit of 50 session
tags; tags from this list are dropped in reverse priority order if your
`custom-tags` set plus the protected set exceeds this limit.
**Droppable tags** are automatically added to the set of default session tags.
If the session tags exceed the [packed size limit][packed-size-limit], these
tags will be dropped, and the AssumeRole call will be retried. If it still
fails, the action will error out. (It is difficult to predict the packed size
before making the call, as session tags and session policies are compressed into
a binary format as part of the call.)
| Key | Value | Priority |
| --------------- | ----------------------- | -------- |
| EventName | GITHUB_EVENT_NAME | 1 |
| BaseRef | GITHUB_BASE_REF | 2 |
| HeadRef | GITHUB_HEAD_REF | 3 |
| RefName | GITHUB_REF_NAME | 4 |
| RunId | GITHUB_RUN_ID | 5 |
| RefType | GITHUB_REF_TYPE | 6 |
| Job | GITHUB_JOB | 7 |
| TriggeringActor | GITHUB_TRIGGERING_ACTOR | 8 |
[packed-size-limit]:
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_know
| Key | Value |
| --------------- | ----------------------- |
| EventName | GITHUB_EVENT_NAME |
| BaseRef | GITHUB_BASE_REF |
| HeadRef | GITHUB_HEAD_REF |
| RunId | GITHUB_RUN_ID |
| Job | GITHUB_JOB |
| TriggeringActor | GITHUB_TRIGGERING_ACTOR |
Tags whose source environment variable is unset are omitted (e.g., `BaseRef` and
`HeadRef` are only set on `pull_request` events).
@ -385,21 +390,21 @@ Tags whose source environment variable is unset are omitted (e.g., `BaseRef` and
_Note: all tag values must conform to
[the tag requirements][sts-tag-requirements].
Values longer than 256 characters will be truncated, and characters outside the
allowed set will be replaced with an underscore (`_`).\_
allowed set will be replaced with an underscore (`_`)._
[sts-tag-requirements]:
https://docs.aws.amazon.com/STS/latest/APIReference/API_Tag.html
The action will use session tagging by default unless you are using OIDC.
The action will use session tagging by default unless you are using OIDC or a
Web Identify Token File.
To [forward session tags to subsequent sessions in a role
chain][session-tag-chaining], you can use
chain][session-tag-chaining], you can use the `transitive-tag-keys` input to
specify the keys of the tags to be passed.
[session-tag-chaining]:
https://docs.aws.amazon.com/IAM/latest/UserGuide/id_session-tags.html#id_session-tags_role-chaining
the `transitive-tag-keys` input to specify the keys of the tags to be passed.
_Note that all subsequent roles in the chain must have
`role-skip-session-tagging` set to `true`_
@ -416,9 +421,10 @@ with:
### Custom session tags
You can add custom session tags using the `custom-tags` input, which accepts a
JSON object. Custom tags cannot override protected tags, but they can override
overrideable tags (in which case the overrideable tag's slot is freed for the
next overrideable tag in the priority list, if any).
JSON object. Custom tags cannot override existing tags. Note that AWS allows a
maximum of 50 tags (so you can supply a maximum of 43 custom tags), although it
is likely that you will exceed the [packed size limit][packed-size-limit]
before you exceed the maximum number of tags.
```yaml
uses: aws-actions/configure-aws-credentials@v6
@ -617,6 +623,35 @@ For further information on OIDC and GitHub Actions, please see:
- [GitHub docs: Configuring OpenID Connect in Amazon Web Services](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/configuring-openid-connect-in-amazon-web-services)
- [GitHub changelog: GitHub Actions: Secure cloud deployments with OpenID Connect](https://github.blog/changelog/2021-10-27-github-actions-secure-cloud-deployments-with-openid-connect/)
## Getting Credentials in AWS Self-Hosted Runners
If you are running GitHub Actions in a self-hosted runner using an AWS Service
(such as Codebuild or EKS) and you have properly configured the service,
credentials should be available by default; the AWS CLI will fetch credentials
using the AWS_CONTAINER_CREDENTIALS_FULL_URI or
AWS_CONTAINER_CREDENTIALS_RELATIVE_URI environment variables. However, you may
still want to use this action if you need to export those credentials for use
with other tools in your workflow. You may also want to use this action in
scenarios where you need to use that 'default' role to assume another role.
To export credentials, simply run the action with `role-to-assume` set to the
default role of the container.
To assume another role from the container's default role, use the
`role-chaining: true` flag, so that the action fetches the default credentials
from the environment before assuming the other role.
If you are using EKS Pod Identities and encountering an error related to the
packed size of session tags, you must either run the action with
`role-skip-session-tagging: true` to disable the tags set by the action, or
[disable EKS session tagging][eks-disable-session-tagging] in the EKS settings
to disable the tags that are automatically set by the EKS Pod Identity Service.
Check the values of the action's session tags and the session tags that are
added by EKS so you can keep the set of tags which is more useful to you.
[eks-disable-session-tagging]:
https://docs.aws.amazon.com/eks/latest/userguide/pod-id-abac.html#pod-id-abac-tags
## Compatibility with non-GitHub Actions environments
This action has been sucessfully tested with

View file

@ -2,7 +2,11 @@ import assert from 'node:assert';
import path from 'node:path';
import * as core from '@actions/core';
import type { AssumeRoleCommandInput, STSClient, Tag } from '@aws-sdk/client-sts';
import { AssumeRoleCommand, AssumeRoleWithWebIdentityCommand } from '@aws-sdk/client-sts';
import {
AssumeRoleCommand,
AssumeRoleWithWebIdentityCommand,
PackedPolicyTooLargeException,
} from '@aws-sdk/client-sts';
import type { CredentialsClient } from './CredentialsClient';
import { errorMessage, isDefined, readFileUtf8, sanitizeGitHubVariables } from './helpers';
@ -42,6 +46,7 @@ async function assumeRoleWithWebIdentityTokenFile(
core.info('Assuming role with web identity token file');
try {
delete params.Tags;
delete params.TransitiveTagKeys;
const creds = await client.send(
new AssumeRoleWithWebIdentityCommand({
...params,
@ -60,6 +65,13 @@ async function assumeRoleWithCredentials(params: AssumeRoleCommandInput, client:
const creds = await client.send(new AssumeRoleCommand({ ...params }));
return creds;
} catch (error) {
if (error instanceof PackedPolicyTooLargeException) {
core.info('Session tag size is too large; dropping droppable tags and retrying.');
const droppableKeys = new Set(DROPPABLE_TAG_SOURCES.map((s) => s.key));
params.Tags = params.Tags?.filter((tag) => !droppableKeys.has(tag.Key ?? ''));
const creds = await client.send(new AssumeRoleCommand({ ...params }));
return creds;
}
throw new Error(`Could not assume role with user credentials: ${errorMessage(error)}`);
}
}
@ -86,8 +98,8 @@ const MAX_TAG_KEY_LENGTH = 128;
const MAX_TAG_VALUE_LENGTH = 256;
const MAX_SESSION_TAGS = 50;
// Identity/audit primitives. Always emitted and cannot be overridden by custom-tags.
const PROTECTED_TAG_SOURCES: ReadonlyArray<{ key: string; envVar: string }> = [
// Identity/audit primitives. Always emitted and cannot be dropped.
const NON_DROPPABLE_TAG_SOURCES: ReadonlyArray<{ key: string; envVar: string }> = [
{ key: 'Repository', envVar: 'GITHUB_REPOSITORY' },
{ key: 'Workflow', envVar: 'GITHUB_WORKFLOW' },
{ key: 'Action', envVar: 'GITHUB_ACTION' },
@ -96,21 +108,22 @@ const PROTECTED_TAG_SOURCES: ReadonlyArray<{ key: string; envVar: string }> = [
{ key: 'Branch', envVar: 'GITHUB_REF' },
];
// Convenience metadata. Custom-tags may override (suppresses the default for that key).
// Listed in priority order; lower-priority entries are dropped first if the user's custom-tags
// would push the total above MAX_SESSION_TAGS.
const OVERRIDEABLE_TAG_SOURCES_BY_PRIORITY: ReadonlyArray<{ key: string; envVar: string }> = [
// Convenience metadata. If the AssumeRole call fails due to compressed size of
// session tags being too large, we will drop these tags and retry once.
const DROPPABLE_TAG_SOURCES: ReadonlyArray<{ key: string; envVar: string }> = [
{ key: 'EventName', envVar: 'GITHUB_EVENT_NAME' },
{ key: 'BaseRef', envVar: 'GITHUB_BASE_REF' },
{ key: 'HeadRef', envVar: 'GITHUB_HEAD_REF' },
{ key: 'RefName', envVar: 'GITHUB_REF_NAME' },
{ key: 'RunId', envVar: 'GITHUB_RUN_ID' },
{ key: 'RefType', envVar: 'GITHUB_REF_TYPE' },
{ key: 'Job', envVar: 'GITHUB_JOB' },
{ key: 'TriggeringActor', envVar: 'GITHUB_TRIGGERING_ACTOR' },
];
const PROTECTED_TAG_KEYS = new Set<string>(['GitHub', ...PROTECTED_TAG_SOURCES.map((s) => s.key)]);
const PROTECTED_TAG_KEYS = new Set<string>([
'GitHub',
...NON_DROPPABLE_TAG_SOURCES.map((s) => s.key),
...DROPPABLE_TAG_SOURCES.map((s) => s.key),
]);
export function parseAndValidateCustomTags(customTags: string, existingTags: Tag[]): Tag[] {
let parsed: unknown;
@ -197,7 +210,13 @@ export async function assumeRole(params: assumeRoleParams) {
// Build session tags. Values are sanitized because the AWS tag value spec is more
// restrictive than permissible characters in environment variables.
const protectedTags: Tag[] = [{ Key: 'GitHub', Value: 'Actions' }];
for (const { key, envVar } of PROTECTED_TAG_SOURCES) {
for (const { key, envVar } of NON_DROPPABLE_TAG_SOURCES) {
const value = process.env[envVar];
if (value) {
protectedTags.push({ Key: key, Value: sanitizeGitHubVariables(value) });
}
}
for (const { key, envVar } of DROPPABLE_TAG_SOURCES) {
const value = process.env[envVar];
if (value) {
protectedTags.push({ Key: key, Value: sanitizeGitHubVariables(value) });
@ -205,26 +224,15 @@ export async function assumeRole(params: assumeRoleParams) {
}
const parsedCustomTags: Tag[] = customTags ? parseAndValidateCustomTags(customTags, protectedTags) : [];
const customTagKeys = new Set(parsedCustomTags.map((t) => t.Key));
const availableOverrideableSlots = MAX_SESSION_TAGS - protectedTags.length - parsedCustomTags.length;
const overrideableTags: Tag[] = [];
for (const { key, envVar } of OVERRIDEABLE_TAG_SOURCES_BY_PRIORITY) {
if (overrideableTags.length >= availableOverrideableSlots) break;
if (customTagKeys.has(key)) continue;
const value = process.env[envVar];
if (value) {
overrideableTags.push({ Key: key, Value: sanitizeGitHubVariables(value) });
}
}
const tagArray: Tag[] = [...protectedTags, ...overrideableTags, ...parsedCustomTags];
const tagArray: Tag[] = [...protectedTags, ...parsedCustomTags];
const tags = roleSkipSessionTagging ? undefined : tagArray;
if (!tags) {
core.debug('Role session tagging has been skipped.');
} else {
core.debug(`${tags.length} role session tags are being used:`);
core.debug(JSON.stringify(tagArray));
}
//only populate transitiveTagKeys array if user is actually using session tagging

View file

@ -3,6 +3,7 @@ import {
AssumeRoleCommand,
AssumeRoleWithWebIdentityCommand,
GetCallerIdentityCommand,
PackedPolicyTooLargeException,
STSClient,
} from '@aws-sdk/client-sts';
import { mockClient } from 'aws-sdk-client-mock';
@ -202,6 +203,18 @@ describe('Configure AWS Credentials', {}, () => {
expect(core.setOutput).toHaveBeenCalledTimes(2);
expect(core.setFailed).not.toHaveBeenCalled();
});
it('does not send Tags or TransitiveTagKeys to AssumeRoleWithWebIdentity', async () => {
// AssumeRoleWithWebIdentity reads session tags from JWT claims, not the request.
// Both fields must be stripped before the STS call.
vi.mocked(core.getMultilineInput).mockImplementation((name: string) => {
if (name === 'transitive-tag-keys') return ['Repository'];
return [];
});
await run();
const callInput = mockedSTSClient.commandCalls(AssumeRoleWithWebIdentityCommand)[0].args[0].input;
expect(callInput.Tags).toBeUndefined();
expect(callInput.TransitiveTagKeys).toBeUndefined();
});
});
describe('Assume existing role', {}, () => {
@ -282,9 +295,9 @@ describe('Configure AWS Credentials', {}, () => {
await run();
const tags = mockedSTSClient.commandCalls(AssumeRoleCommand)[0].args[0].input.Tags ?? [];
// 7 protected (GitHub + Repository, Workflow, Action, Actor, Commit, Branch)
// + 8 overrideable (EventName, BaseRef, HeadRef, RefName, RunId, RefType, Job, TriggeringActor).
// No custom-tags, all env vars set in mocks.envs → all 15 should be present, nothing else.
expect(tags).toHaveLength(15);
// + 6 droppable (EventName, BaseRef, HeadRef, RunId, Job, TriggeringActor).
// No custom-tags, all env vars set in mocks.envs → all 13 should be present, nothing else.
expect(tags).toHaveLength(13);
const tagsByKey = Object.fromEntries(tags.map((t) => [t.Key, t.Value]));
expect(tagsByKey).toEqual({
GitHub: 'Actions',
@ -297,14 +310,12 @@ describe('Configure AWS Credentials', {}, () => {
EventName: 'pull_request',
BaseRef: 'main',
HeadRef: 'feature-branch',
RefName: 'feature-branch',
RunId: '16412345678',
RefType: 'branch',
Job: 'build',
TriggeringActor: 'MY-USERNAME_bot_',
});
});
it('omits overrideable tags whose env vars are unset', {}, async () => {
it('omits droppable tags whose env vars are unset', {}, async () => {
vi.mocked(core.getInput).mockImplementation(mocks.getInput(mocks.IAM_ASSUMEROLE_INPUTS));
delete process.env.GITHUB_BASE_REF;
delete process.env.GITHUB_HEAD_REF;
@ -318,6 +329,27 @@ describe('Configure AWS Credentials', {}, () => {
expect(tagKeys).toContain('EventName');
expect(tagKeys).toContain('RunId');
});
it('drops droppable tags and retries on PackedPolicyTooLargeException', {}, async () => {
vi.mocked(core.getInput).mockImplementation(mocks.getInput(mocks.IAM_ASSUMEROLE_INPUTS));
mockedSTSClient
.on(AssumeRoleCommand)
.rejectsOnce(new PackedPolicyTooLargeException({ message: 'too large', $metadata: {} }))
.resolvesOnce(mocks.outputs.STS_CREDENTIALS);
await run();
expect(core.info).toHaveBeenCalledWith('Session tag size is too large; dropping droppable tags and retrying.');
const retryInput = mockedSTSClient.commandCalls(AssumeRoleCommand)[1].args[0].input;
const retryTagKeys = (retryInput.Tags ?? []).map((t) => t.Key);
expect(retryTagKeys).not.toContain('EventName');
expect(retryTagKeys).not.toContain('BaseRef');
expect(retryTagKeys).not.toContain('HeadRef');
expect(retryTagKeys).not.toContain('RunId');
expect(retryTagKeys).not.toContain('Job');
expect(retryTagKeys).not.toContain('TriggeringActor');
// Protected tags remain
expect(retryTagKeys).toContain('GitHub');
expect(retryTagKeys).toContain('Repository');
expect(core.setFailed).not.toHaveBeenCalled();
});
it('sanitizes invalid characters in env-derived tag values', {}, async () => {
vi.mocked(core.getInput).mockImplementation(mocks.getInput(mocks.IAM_ASSUMEROLE_INPUTS));
process.env.GITHUB_HEAD_REF = 'feature/has spaces&bad?chars';
@ -370,8 +402,6 @@ describe('Configure AWS Credentials', {}, () => {
{ Key: 'EventName', Value: 'pull_request' },
{ Key: 'RunId', Value: '16412345678' },
{ Key: 'Job', Value: 'build' },
{ Key: 'RefName', Value: 'feature-branch' },
{ Key: 'RefType', Value: 'branch' },
{ Key: 'TriggeringActor', Value: 'MY-USERNAME_bot_' },
{ Key: 'Environment', Value: 'Production' },
{ Key: 'Team', Value: 'DevOps' },
@ -420,7 +450,7 @@ describe('Configure AWS Credentials', {}, () => {
await run();
expect(core.warning).toHaveBeenCalledWith(expect.stringContaining("'custom-tags' is set but will be ignored"));
});
it('lets custom tags override overrideable default tag keys', {}, async () => {
it('rejects custom tags that conflict with droppable tag keys', {}, async () => {
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({
...mocks.IAM_ASSUMEROLE_INPUTS,
@ -428,13 +458,10 @@ describe('Configure AWS Credentials', {}, () => {
}),
);
await run();
const tags = mockedSTSClient.commandCalls(AssumeRoleCommand)[0].args[0].input.Tags ?? [];
const eventNameTags = tags.filter((t) => t.Key === 'EventName');
const baseRefTags = tags.filter((t) => t.Key === 'BaseRef');
expect(eventNameTags).toHaveLength(1);
expect(eventNameTags[0]?.Value).toBe('workflow_dispatch');
expect(baseRefTags).toHaveLength(1);
expect(baseRefTags[0]?.Value).toBe('release/2026');
expect(core.setFailed).toHaveBeenCalledWith(
"custom-tags: key 'EventName' conflicts with a protected session tag set by this action and cannot be overridden",
);
expect(mockedSTSClient.commandCalls(AssumeRoleCommand)).toHaveLength(0);
});
it('rejects custom tags that conflict with the protected Branch tag', {}, async () => {
// Regression guard: Branch was a default before v6.2 and must remain unoverridable.
@ -450,62 +477,10 @@ describe('Configure AWS Credentials', {}, () => {
);
expect(mockedSTSClient.commandCalls(AssumeRoleCommand)).toHaveLength(0);
});
it('drops lower-priority overrideable tags when custom-tags would exceed the session-tag limit', {}, async () => {
// 7 protected (GitHub + 6 from PROTECTED_TAG_SOURCES) + 40 custom = 47 used → 3 overrideable slots.
// The first 3 overrideable tags by priority are EventName, BaseRef, HeadRef (RefName, RunId, RefType,
// Job, TriggeringActor must be dropped).
it('rejects custom-tags that would exceed the session-tag limit', {}, async () => {
// 13 existing tags (7 non-droppable + 6 droppable) + 38 custom = 51 > 50.
const customTagsObj: Record<string, string> = {};
for (let i = 0; i < 40; i++) {
customTagsObj[`Custom${i}`] = `value${i}`;
}
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({
...mocks.IAM_ASSUMEROLE_INPUTS,
'custom-tags': JSON.stringify(customTagsObj),
}),
);
await run();
const tags = mockedSTSClient.commandCalls(AssumeRoleCommand)[0].args[0].input.Tags ?? [];
const tagKeys = tags.map((t) => t.Key);
expect(tags).toHaveLength(50);
expect(tagKeys).toContain('Branch');
expect(tagKeys).toContain('EventName');
expect(tagKeys).toContain('BaseRef');
expect(tagKeys).toContain('HeadRef');
expect(tagKeys).not.toContain('RefName');
expect(tagKeys).not.toContain('RunId');
expect(tagKeys).not.toContain('RefType');
expect(tagKeys).not.toContain('Job');
expect(tagKeys).not.toContain('TriggeringActor');
});
it('overridden overrideable tags free a slot for a lower-priority overrideable tag', {}, async () => {
// Same 40-custom-tag scenario as above, but one of the customs overrides BaseRef.
// BaseRef no longer competes for the overrideable budget, so the next-priority overrideable (RefName) gets in.
const customTagsObj: Record<string, string> = { BaseRef: 'release/2026' };
for (let i = 0; i < 39; i++) {
customTagsObj[`Custom${i}`] = `value${i}`;
}
vi.mocked(core.getInput).mockImplementation(
mocks.getInput({
...mocks.IAM_ASSUMEROLE_INPUTS,
'custom-tags': JSON.stringify(customTagsObj),
}),
);
await run();
const tags = mockedSTSClient.commandCalls(AssumeRoleCommand)[0].args[0].input.Tags ?? [];
const tagKeys = tags.map((t) => t.Key);
expect(tags).toHaveLength(50);
expect(tagKeys).toContain('Branch');
expect(tagKeys).toContain('EventName');
expect(tagKeys).toContain('BaseRef');
expect(tagKeys).toContain('HeadRef');
expect(tagKeys).toContain('RefName');
expect(tagKeys).not.toContain('RunId');
});
it('rejects custom-tags that would exceed the session-tag limit on their own', {}, async () => {
// 7 protected + 44 custom = 51, which is over 50 even with zero overrideable tags.
const customTagsObj: Record<string, string> = {};
for (let i = 0; i < 44; i++) {
for (let i = 0; i < 38; i++) {
customTagsObj[`Custom${i}`] = `value${i}`;
}
vi.mocked(core.getInput).mockImplementation(
@ -518,12 +493,10 @@ describe('Configure AWS Credentials', {}, () => {
expect(core.setFailed).toHaveBeenCalledWith(expect.stringContaining('would exceed the AWS limit of 50'));
expect(mockedSTSClient.commandCalls(AssumeRoleCommand)).toHaveLength(0);
});
it('drops transitive-tag-keys entries that refer to evicted overrideable tags', {}, async () => {
// Force eviction of all overrideable tags below EventName/BaseRef/HeadRef. The user transitive-tags
// RunId (which gets evicted) and Repository (which is protected and stays). The TransitiveTagKeys
// payload must include only the keys that actually appear in Tags.
it('allows custom-tags up to the session-tag limit', {}, async () => {
// 13 existing tags + 37 custom = 50, exactly at the limit.
const customTagsObj: Record<string, string> = {};
for (let i = 0; i < 40; i++) {
for (let i = 0; i < 37; i++) {
customTagsObj[`Custom${i}`] = `value${i}`;
}
vi.mocked(core.getInput).mockImplementation(
@ -532,15 +505,10 @@ describe('Configure AWS Credentials', {}, () => {
'custom-tags': JSON.stringify(customTagsObj),
}),
);
vi.mocked(core.getMultilineInput).mockImplementation((name: string) => {
if (name === 'transitive-tag-keys') return ['Repository', 'RunId'];
return [];
});
await run();
const callInput = mockedSTSClient.commandCalls(AssumeRoleCommand)[0].args[0].input;
const tagKeys = (callInput.Tags ?? []).map((t) => t.Key);
expect(tagKeys).not.toContain('RunId');
expect(callInput.TransitiveTagKeys).toEqual(['Repository']);
expect(core.setFailed).not.toHaveBeenCalled();
const tags = mockedSTSClient.commandCalls(AssumeRoleCommand)[0].args[0].input.Tags ?? [];
expect(tags).toHaveLength(50);
});
});

View file

@ -105,8 +105,6 @@ const envs = {
GITHUB_EVENT_NAME: 'pull_request',
GITHUB_RUN_ID: '16412345678',
GITHUB_JOB: 'build',
GITHUB_REF_NAME: 'feature-branch',
GITHUB_REF_TYPE: 'branch',
GITHUB_BASE_REF: 'main',
GITHUB_HEAD_REF: 'feature-branch',
GITHUB_TRIGGERING_ACTOR: 'MY-USERNAME[bot]',