Skip to content

fix: add plan-time validation to key_prefix in autolink reference resource (#3176)#3277

Open
LeC-D wants to merge 3 commits into
integrations:mainfrom
LeC-D:fix/autolink-key-prefix-validation
Open

fix: add plan-time validation to key_prefix in autolink reference resource (#3176)#3277
LeC-D wants to merge 3 commits into
integrations:mainfrom
LeC-D:fix/autolink-key-prefix-validation

Conversation

@LeC-D

@LeC-D LeC-D commented Mar 15, 2026

Copy link
Copy Markdown

Summary

Fixes #3176

Problem

terraform plan accepts any value for key_prefix in github_repository_autolink_reference, but terraform apply can fail with a 422 from the GitHub API if the value is invalid:

key_prefix must not end with a number
key_prefix must only contain letters, numbers, or .-_+=:/#

This creates a confusing plan/apply inconsistency where the plan shows a clean diff but apply fails.

Fix

Added ValidateDiagFunc to the key_prefix schema field using a regexp that mirrors GitHub's API constraints:

  • Allowed characters: letters, digits, and .-_+=:/#
  • Must not end with a digit
ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(
    regexp.MustCompile(`^[a-zA-Z0-9.=+:/#_-]*[a-zA-Z.=+:/#_-]$`),
    "must only contain letters, numbers, or .-_+=:/# and must not end with a number",
)),

Both regexp and validation were already imported in this file (used by target_url_template). No new dependencies needed.

Testing

Existing acceptance tests use key_prefix values like TEST1-, TEST2-, etc. which all pass the new validation. Invalid values like PTFY25 (ends with digit) will now be caught at plan time.

@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for this contribution! Just to let you know, our GitHub SDK team does a round of issue and PR reviews twice a week, every Monday and Friday! We have a process in place for prioritizing and responding to your input. Because you are a part of this community please feel free to comment, add to, or pick up any issues/PRs that are labeled with Status: Up for grabs. You & others like you are the reason all of this works! So thank you & happy coding! 🚀

@github-actions github-actions Bot added the Type: Bug Something isn't working as documented label Mar 15, 2026
austenstone

This comment was marked as duplicate.

@austenstone austenstone left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Left a concrete regression-test suggestion so the fix is covered at plan time as well as in the schema.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This validation looks right. I think the missing piece is a regression test that proves invalid prefixes now fail during terraform plan, since that’s the behavior this PR is fixing.

Because this PR only changes this file, I can’t attach a native GitHub suggestion directly to github/resource_github_repository_autolink_reference_test.go, but something along these lines would lock it in:

t.Run("rejects invalid key_prefix at plan time", func(t *testing.T) {
	randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
	repoName := fmt.Sprintf("%srepo-autolink-%s", testResourcePrefix, randomID)
	config := fmt.Sprintf(`
		resource "github_repository" "test" {
			name        = "%s"
			description = "Test autolink validation"
		}

		resource "github_repository_autolink_reference" "invalid" {
			repository = github_repository.test.name

			key_prefix          = "PTFY25"
			target_url_template = "https://example.com/PTFY-<num>"
		}
	`, repoName)

	resource.Test(t, resource.TestCase{
		PreCheck:          func() { skipUnauthenticated(t) },
		ProviderFactories: providerFactories,
		Steps: []resource.TestStep{
			{
				Config:      config,
				ExpectError: regexp.MustCompile(`must only contain letters, numbers, or .* must not end with a number`),
			},
		},
	})
})

That would make sure we don’t regress back to the current plan/apply mismatch later.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch! Added a resource.UnitTest sub-test that passes key_prefix = "PTFY25" (ends with a digit) and asserts a plan-time error matching must not end with a number. The test uses providerFactories and doesn't require a real GitHub account.

@LeC-D

LeC-D commented Mar 16, 2026

Copy link
Copy Markdown
Author

Good call! Added a resource.UnitTest sub-test in resource_github_repository_autolink_reference_test.go that passes key_prefix = "PTFY25" (ends with a digit) and asserts a plan-time error matching must not end with a number. This locks in the validation behavior without requiring a real GitHub account.

@LeC-D LeC-D force-pushed the fix/autolink-key-prefix-validation branch from d721ddc to 49a967c Compare March 18, 2026 22:02
@LeC-D

LeC-D commented Mar 18, 2026

Copy link
Copy Markdown
Author

Rebased on upstream main to bring the branch up to date.

Comment on lines +72 to +75
ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(
regexp.MustCompile(`^[a-zA-Z0-9.=+:/#_-]*[a-zA-Z.=+:/#_-]$`),
"must only contain letters, numbers, or .-_+=:/# and must not end with a number",
)),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

suggestion: use 2 validations, one for suffix and one for allowed chars.
And the must not end with could be simplified to \D$ I think

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Done — split into two StringMatch validators inside validation.All(): one for allowed characters (^[a-zA-Z0-9.=+:/#_-]+$) and one for the digit-suffix check using \D$ as you suggested. Error messages are now separate and targeted.

@LeC-D

LeC-D commented Mar 19, 2026

Copy link
Copy Markdown
Author

Applied @deiga's review feedback: split the key_prefix validation into two separate StringMatch validators inside validation.All() — one for allowed characters (^[a-zA-Z0-9.=+:/#_-]+$) and one for the digit-suffix check (\D$). Error messages are now more targeted. Thanks for the suggestion!

@deiga deiga added this to the v6.12.0 Release milestone Mar 20, 2026
LeC-D added 3 commits March 24, 2026 10:06
…egrations#3176)

GitHub's API enforces that key_prefix:
- must only contain letters, numbers, or .-_+=:/#
- must not end with a number

Without client-side validation, terraform plan succeeds with an invalid
key_prefix (e.g. 'PTFY25') but terraform apply fails with a 422 from
the GitHub API, giving a confusing plan/apply inconsistency.

Added ValidateDiagFunc using a regexp that mirrors the API constraints,
so invalid key_prefix values are caught at plan time.
Adds a plan-time validation test asserting that a key_prefix ending
in a digit (e.g. PTFY25) is rejected before any API call is made.
Addresses review comment from @austenstone.
Per review by @deiga: use two StringMatch validators inside
validation.All() — one for allowed characters (^[a-zA-Z0-9.=+:/#_-]+$)
and one for the digit-suffix check (\D$) — instead of a single
combined regex. This makes the error messages more precise.
@LeC-D LeC-D force-pushed the fix/autolink-key-prefix-validation branch from 3e5df52 to b1015f6 Compare March 24, 2026 14:06
@LeC-D

LeC-D commented Mar 24, 2026

Copy link
Copy Markdown
Author

Rebased on upstream main (2026-03-24) to bring the branch back up to date.

@LeC-D

LeC-D commented Mar 26, 2026

Copy link
Copy Markdown
Author

Rebased on upstream main (2026-03-26) to bring the branch back up to date.

@LeC-D

LeC-D commented Mar 28, 2026

Copy link
Copy Markdown
Author

@deiga The CHANGES_REQUESTED feedback has been addressed in the latest commit (b1015f6) — the key_prefix validation is now split into two separate StringMatch validators inside validation.All() as suggested. Would appreciate a re-review when you get a chance!

@LeC-D

LeC-D commented Mar 28, 2026

Copy link
Copy Markdown
Author

Rebased on upstream main (2026-03-28) to bring the branch back up to date.

@LeC-D

LeC-D commented Mar 28, 2026

Copy link
Copy Markdown
Author

Rebased on upstream main (2026-03-28) to bring the branch back up to date.

@deiga deiga removed the request for review from robert-crandall May 6, 2026 12:36
@deiga deiga removed the request for review from stevehipwell May 17, 2026 13:24
@deiga

deiga commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

@LeC-D Sorry that this has taken long to get to. Would you be available to rebase this (possibly multiple times) during the next week? We're trying to get 6.13.0 out and will try to merge as many ~ready PRs as is reasonable

@stevehipwell stevehipwell left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@LeC-D please could you rebase this PR?

Comment on lines +72 to +81
ValidateDiagFunc: validation.ToDiagFunc(validation.All(
validation.StringMatch(
regexp.MustCompile(`^[a-zA-Z0-9.=+:/#_-]+$`),
"must only contain letters, numbers, or the characters .-_+=:/#",
),
validation.StringMatch(
regexp.MustCompile(`\D$`),
"must not end with a number",
),
)),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
ValidateDiagFunc: validation.ToDiagFunc(validation.All(
validation.StringMatch(
regexp.MustCompile(`^[a-zA-Z0-9.=+:/#_-]+$`),
"must only contain letters, numbers, or the characters .-_+=:/#",
),
validation.StringMatch(
regexp.MustCompile(`\D$`),
"must not end with a number",
),
)),
ValidateDiagFunc: validation.ToDiagFunc(validation.StringMatch(
regexp.MustCompile(`^[a-zA-Z0-9.=+:/#_-]+\D$`),
"must only contain letters, numbers, or the characters .-_+=:/# and not end with a number",
)),

There is no reason to use two validators for this. Also could you confirm the logic for the start of the prefix can actually include all or the allowed characters?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Awaiting response Type: Bug Something isn't working as documented

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: autolink allows numbers during plan, but fails during apply

4 participants