From c634707882d8961ac739fdd651285bf7c0ddf4f9 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 18:42:17 +0200 Subject: [PATCH 01/19] Improve docs of importing `github_repository_file` Signed-off-by: Timo Sand --- website/docs/r/repository_file.html.markdown | 48 +++++++++----------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/website/docs/r/repository_file.html.markdown b/website/docs/r/repository_file.html.markdown index cf614f9912..cc1a70487b 100644 --- a/website/docs/r/repository_file.html.markdown +++ b/website/docs/r/repository_file.html.markdown @@ -15,10 +15,11 @@ GitHub repository. ## Example Usage ### Existing Branch + ```hcl resource "github_repository" "foo" { - name = "tf-acc-test-%s" + name = "example" auto_init = true } @@ -36,10 +37,11 @@ resource "github_repository_file" "foo" { ``` ### Auto Created Branch + ```hcl resource "github_repository" "foo" { - name = "tf-acc-test-%s" + name = "example" auto_init = true } @@ -57,55 +59,47 @@ resource "github_repository_file" "foo" { ``` - ## Argument Reference The following arguments are supported: -* `repository` - (Required) The repository to create the file in. +- `repository` - (Required) The repository to create the file in. -* `file` - (Required) The path of the file to manage. +- `file` - (Required) The path of the file to manage. -* `content` - (Required) The file content. +- `content` - (Required) The file content. -* `branch` - (Optional) Git branch (defaults to the repository's default branch). +- `branch` - (Optional) Git branch (defaults to the repository's default branch). The branch must already exist, it will only be created automatically if 'autocreate_branch' is set true. -* `commit_author` - (Optional) Committer author name to use. **NOTE:** GitHub app users may omit author and email information so GitHub can verify commits as the GitHub App. This maybe useful when a branch protection rule requires signed commits. +- `commit_author` - (Optional) Committer author name to use. **NOTE:** GitHub app users may omit author and email information so GitHub can verify commits as the GitHub App. This maybe useful when a branch protection rule requires signed commits. -* `commit_email` - (Optional) Committer email address to use. **NOTE:** GitHub app users may omit author and email information so GitHub can verify commits as the GitHub App. This may be useful when a branch protection rule requires signed commits. +- `commit_email` - (Optional) Committer email address to use. **NOTE:** GitHub app users may omit author and email information so GitHub can verify commits as the GitHub App. This may be useful when a branch protection rule requires signed commits. -* `commit_message` - (Optional) The commit message when creating, updating or deleting the managed file. +- `commit_message` - (Optional) The commit message when creating, updating or deleting the managed file. -* `overwrite_on_create` - (Optional) Enable overwriting existing files. If set to `true` it will overwrite an existing file with the same name. If set to `false` it will fail if there is an existing file with the same name. +- `overwrite_on_create` - (Optional) Enable overwriting existing files. If set to `true` it will overwrite an existing file with the same name. If set to `false` it will fail if there is an existing file with the same name. -* `autocreate_branch` - (Optional) Automatically create the branch if it could not be found. Defaults to false. Subsequent reads if the branch is deleted will occur from 'autocreate_branch_source_branch'. +- `autocreate_branch` - (Optional) Automatically create the branch if it could not be found. Defaults to false. Subsequent reads if the branch is deleted will occur from 'autocreate_branch_source_branch'. -* `autocreate_branch_source_branch` - (Optional) The branch name to start from, if 'autocreate_branch' is set. Defaults to 'main'. +- `autocreate_branch_source_branch` - (Optional) The branch name to start from, if 'autocreate_branch' is set. Defaults to 'main'. -* `autocreate_branch_source_sha` - (Optional) The commit hash to start from, if 'autocreate_branch' is set. Defaults to the tip of 'autocreate_branch_source_branch'. If provided, 'autocreate_branch_source_branch' is ignored. +- `autocreate_branch_source_sha` - (Optional) The commit hash to start from, if 'autocreate_branch' is set. Defaults to the tip of 'autocreate_branch_source_branch'. If provided, 'autocreate_branch_source_branch' is ignored. ## Attributes Reference The following additional attributes are exported: -* `commit_sha` - The SHA of the commit that modified the file. +- `commit_sha` - The SHA of the commit that modified the file. -* `sha` - The SHA blob of the file. - -* `ref` - The name of the commit/branch/tag. +- `sha` - The SHA blob of the file. +- `ref` - The name of the commit/branch/tag. ## Import -Repository files can be imported using a combination of the `repo` and `file`, e.g. +Repository files can be imported using a combination of the `repo`, `file` and `branch`, e.g. -``` -$ terraform import github_repository_file.gitignore example/.gitignore -``` - -To import a file from a branch other than the default branch, append `:` and the branch name, e.g. - -``` -$ terraform import github_repository_file.gitignore example/.gitignore:dev +```sh +terraform import github_repository_file.gitignore example/.gitignore:main ``` From 3965ecb7e4f237d62db12a82d3a3dbc74810bf8b Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 18:51:32 +0200 Subject: [PATCH 02/19] Add missing test for import Signed-off-by: Timo Sand --- .../resource_github_repository_file_test.go | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index 2f11e27311..b0cdb08bd3 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -400,4 +400,69 @@ func TestAccGithubRepositoryFile(t *testing.T) { }, }) }) + t.Run("imports_files_without_error", func(t *testing.T) { + randomID := acctest.RandString(5) + repoName := fmt.Sprintf("%sfile-import-%s", testResourcePrefix, randomID) + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + auto_init = true + vulnerability_alerts = true + } + + resource "github_repository_file" "test" { + repository = github_repository.test.name + file = "test" + content = "bar" + commit_message = "Managed by Terraform" + commit_author = "Terraform User" + commit_email = "terraform@example.com" + } + `, repoName) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnauthenticated(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository_file.test", "content", + "bar", + ), + resource.TestCheckResourceAttr( + "github_repository_file.test", "sha", + "ba0e162e1c47469e3fe4b393a8bf8c569f302116", + ), + resource.TestCheckResourceAttr( + "github_repository_file.test", "ref", + "main", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_author", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_email", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_message", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_sha", + ), + resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch"), + resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_branch"), + resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_sha"), + ), + }, + { + ResourceName: "github_repository_file.test", + ImportState: true, + ImportStateVerify: true, + ImportStateId: fmt.Sprintf("%s/%s:main", repoName, "test"), + }, + }, + }) + }) } From aef6dcf205a46619abf4ca0cdeab6fe9f68e260f Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 19:14:43 +0200 Subject: [PATCH 03/19] Ensure we only set `branch` on import if it's not the default branch Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 14 ++++++++++++-- github/resource_github_repository_file_test.go | 9 +++++---- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 80a169cf2d..6660c5bee4 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -436,10 +436,20 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD owner := meta.(*Owner).name repo, file := splitRepoFilePath(repoFilePath) - opts := &github.RepositoryContentGetOptions{Ref: branch} - if err := d.Set("branch", branch); err != nil { + repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if err != nil { return nil, err } + defaultBranch := repoInfo.GetDefaultBranch() + opts := &github.RepositoryContentGetOptions{} + + if branch != defaultBranch { + opts.Ref = branch + if err := d.Set("branch", branch); err != nil { + return nil, err + } + } + fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, file, opts) if err != nil { return nil, err diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index b0cdb08bd3..dcbff02230 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -457,10 +457,11 @@ func TestAccGithubRepositoryFile(t *testing.T) { ), }, { - ResourceName: "github_repository_file.test", - ImportState: true, - ImportStateVerify: true, - ImportStateId: fmt.Sprintf("%s/%s:main", repoName, "test"), + ResourceName: "github_repository_file.test", + ImportState: true, + ImportStateVerify: true, + ImportStateId: fmt.Sprintf("%s/%s:main", repoName, "test"), + ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. }, }, }) From 6b2938f5ce78c4fe69bf1c799bba2ce56850f4b8 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 20:46:01 +0200 Subject: [PATCH 04/19] Update `branch` to `Computed` field Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 35 +++++++--- .../resource_github_repository_file_test.go | 65 +++++++++++++++++++ 2 files changed, 91 insertions(+), 9 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 6660c5bee4..72307bfefd 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -6,6 +6,7 @@ import ( "fmt" "net/http" "net/url" + "strings" "github.com/google/go-github/v82/github" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -47,6 +48,7 @@ func resourceGithubRepositoryFile() *schema.Resource { Type: schema.TypeString, Optional: true, ForceNew: true, + Computed: true, Description: "The branch name, defaults to the repository's default branch", }, "ref": { @@ -175,6 +177,14 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD } } checkOpt.Ref = branch.(string) + } else { + repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if err != nil { + return diag.FromErr(err) + } + if err := d.Set("branch", repoInfo.GetDefaultBranch()); err != nil { + return diag.FromErr(err) + } } opts := resourceGithubRepositoryFileOptions(d) @@ -427,27 +437,34 @@ func autoBranchDiffSuppressFunc(k, _, _ string, d *schema.ResourceData) bool { } func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { - repoFilePath, branch, err := parseID2(d.Id()) - if err != nil { - return nil, fmt.Errorf("invalid ID specified. Supplied ID must be written as /:. %w", err) + importIDParts := strings.Split(d.Id(), idSeparator) + + if len(importIDParts) > 2 { + return nil, fmt.Errorf("invalid ID specified. Supplied ID must be written as / (when branch is \"main\") or /:") } + repoFilePath := importIDParts[0] client := meta.(*Owner).v3client owner := meta.(*Owner).name repo, file := splitRepoFilePath(repoFilePath) - repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) - if err != nil { - return nil, err - } - defaultBranch := repoInfo.GetDefaultBranch() opts := &github.RepositoryContentGetOptions{} - if branch != defaultBranch { + if len(importIDParts) == 2 { + branch := importIDParts[1] opts.Ref = branch if err := d.Set("branch", branch); err != nil { return nil, err } + } else { + repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if err != nil { + return nil, err + } + defaultBranch := repoInfo.GetDefaultBranch() + if err := d.Set("branch", defaultBranch); err != nil { + return nil, err + } } fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, file, opts) diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index dcbff02230..c984cb7a70 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -420,6 +420,71 @@ func TestAccGithubRepositoryFile(t *testing.T) { } `, repoName) + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnauthenticated(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "github_repository_file.test", "content", + "bar", + ), + resource.TestCheckResourceAttr( + "github_repository_file.test", "sha", + "ba0e162e1c47469e3fe4b393a8bf8c569f302116", + ), + resource.TestCheckResourceAttr( + "github_repository_file.test", "ref", + "main", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_author", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_email", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_message", + ), + resource.TestCheckResourceAttrSet( + "github_repository_file.test", "commit_sha", + ), + resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch"), + resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_branch"), + resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_sha"), + ), + }, + { + ResourceName: "github_repository_file.test", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. + }, + }, + }) + }) + t.Run("imports_files_with_branch_in_id_without_error", func(t *testing.T) { + randomID := acctest.RandString(5) + repoName := fmt.Sprintf("%sfile-import-%s", testResourcePrefix, randomID) + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + auto_init = true + vulnerability_alerts = true + } + + resource "github_repository_file" "test" { + repository = github_repository.test.name + file = "test" + content = "bar" + commit_message = "Managed by Terraform" + commit_author = "Terraform User" + commit_email = "terraform@example.com" + } + `, repoName) + resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, ProviderFactories: providerFactories, From 76e4f346352d775556ae950247abf8478a03fe92 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 22:02:10 +0200 Subject: [PATCH 05/19] Add state migration for missing branch field Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 9 ++ ...source_github_repository_file_migration.go | 115 ++++++++++++++++++ ...e_github_repository_file_migration_test.go | 111 +++++++++++++++++ 3 files changed, 235 insertions(+) create mode 100644 github/resource_github_repository_file_migration.go create mode 100644 github/resource_github_repository_file_migration_test.go diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 72307bfefd..c83a905aa5 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -24,6 +24,15 @@ func resourceGithubRepositoryFile() *schema.Resource { StateContext: resourceGithubRepositoryFileImport, }, + SchemaVersion: 1, + StateUpgraders: []schema.StateUpgrader{ + { + Type: resourceGithubRepositoryFileV0().CoreConfigSchema().ImpliedType(), + Upgrade: resourceGithubRepositoryFileStateUpgradeV0, + Version: 0, + }, + }, + Description: "This resource allows you to create and manage files within a GitHub repository.", Schema: map[string]*schema.Schema{ diff --git a/github/resource_github_repository_file_migration.go b/github/resource_github_repository_file_migration.go new file mode 100644 index 0000000000..5216702d1b --- /dev/null +++ b/github/resource_github_repository_file_migration.go @@ -0,0 +1,115 @@ +package github + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func resourceGithubRepositoryFileV0() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + "repository": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "file": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "content": { + Type: schema.TypeString, + Required: true, + }, + "branch": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "ref": { + Type: schema.TypeString, + Computed: true, + ForceNew: true, + }, + "commit_sha": { + Type: schema.TypeString, + Computed: true, + }, + "commit_message": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, + "commit_author": { + Type: schema.TypeString, + Optional: true, + RequiredWith: []string{"commit_email"}, + }, + "commit_email": { + Type: schema.TypeString, + Optional: true, + RequiredWith: []string{"commit_author"}, + }, + "sha": { + Type: schema.TypeString, + Computed: true, + }, + "overwrite_on_create": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "autocreate_branch": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + "autocreate_branch_source_branch": { + Type: schema.TypeString, + Default: "main", + Optional: true, + RequiredWith: []string{"autocreate_branch"}, + }, + "autocreate_branch_source_sha": { + Type: schema.TypeString, + Optional: true, + Computed: true, + RequiredWith: []string{"autocreate_branch"}, + }, + }, + } +} + +func resourceGithubRepositoryFileStateUpgradeV0(ctx context.Context, rawState map[string]any, m any) (map[string]any, error) { + tflog.Debug(ctx, "GitHub Repository File State before migration", map[string]any{ + "rawState": rawState, + }) + + // If branch is missing or empty, fetch the default branch from the repository + if branch, ok := rawState["branch"].(string); !ok || branch == "" { + meta := m.(*Owner) + client := meta.v3client + owner := meta.name + + repoName, ok := rawState["repository"].(string) + if !ok { + return nil, fmt.Errorf("repository not found or is not a string") + } + + repo, _, err := client.Repositories.Get(ctx, owner, repoName) + if err != nil { + return nil, fmt.Errorf("failed to retrieve repository %s: %w", repoName, err) + } + + rawState["branch"] = repo.GetDefaultBranch() + } + + tflog.Debug(ctx, "GitHub Repository File State after migration", map[string]any{ + "rawState": rawState, + }) + return rawState, nil +} diff --git a/github/resource_github_repository_file_migration_test.go b/github/resource_github_repository_file_migration_test.go new file mode 100644 index 0000000000..e824c43d6e --- /dev/null +++ b/github/resource_github_repository_file_migration_test.go @@ -0,0 +1,111 @@ +package github + +import ( + "context" + "reflect" + "testing" +) + +func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { + t.Parallel() + + for _, d := range []struct { + testName string + rawState map[string]any + want map[string]any + shouldError bool + }{ + { + testName: "preserves_existing_branch", + rawState: map[string]any{ + "id": "test-repo/path/to/file.txt", + "repository": "test-repo", + "file": "path/to/file.txt", + "content": "file content", + "branch": "main", + "commit_sha": "abc123", + "sha": "def456", + "overwrite_on_create": false, + }, + want: map[string]any{ + "id": "test-repo/path/to/file.txt", + "repository": "test-repo", + "file": "path/to/file.txt", + "content": "file content", + "branch": "main", + "commit_sha": "abc123", + "sha": "def456", + "overwrite_on_create": false, + }, + shouldError: false, + }, + { + testName: "preserves_custom_branch", + rawState: map[string]any{ + "id": "test-repo/README.md", + "repository": "test-repo", + "file": "README.md", + "content": "# README", + "branch": "develop", + }, + want: map[string]any{ + "id": "test-repo/README.md", + "repository": "test-repo", + "file": "README.md", + "content": "# README", + "branch": "develop", + }, + shouldError: false, + }, + // TODO: Enable this test once we have a pattern to create a mock client for the test. + // { + // testName: "migrates_with_missing_branch", + // rawState: map[string]any{ + // "id": "test-repo/path/to/file.txt", + // "repository": "test-repo", + // "file": "path/to/file.txt", + // "content": "file content", + // }, + // want: map[string]any{ + // "id": "test-repo/path/to/file.txt", + // "repository": "test-repo", + // "file": "path/to/file.txt", + // "content": "file content", + // "branch": "main", // fetched from API + // }, + // shouldError: false, + // }, + // TODO: Enable this test once we have a pattern to create a mock client for the test. + // { + // testName: "migrates_with_empty_branch", + // rawState: map[string]any{ + // "id": "test-repo/path/to/file.txt", + // "repository": "test-repo", + // "file": "path/to/file.txt", + // "content": "file content", + // "branch": "", + // }, + // want: map[string]any{ + // "id": "test-repo/path/to/file.txt", + // "repository": "test-repo", + // "file": "path/to/file.txt", + // "content": "file content", + // "branch": "main", // fetched from API + // }, + // shouldError: false, + // }, + } { + t.Run(d.testName, func(t *testing.T) { + t.Parallel() + + got, err := resourceGithubRepositoryFileStateUpgradeV0(context.Background(), d.rawState, nil) + if (err != nil) != d.shouldError { + t.Fatalf("unexpected error state: got error %v, shouldError %v", err, d.shouldError) + } + + if !d.shouldError && !reflect.DeepEqual(got, d.want) { + t.Fatalf("got %+v, want %+v", got, d.want) + } + }) + } +} From db068df8af822924ea0411a6cbe1ac252f1c0619 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 22:11:33 +0200 Subject: [PATCH 06/19] Add ID migration in the same bunch Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 8 ++++++-- .../resource_github_repository_file_migration.go | 2 ++ ...ource_github_repository_file_migration_test.go | 15 ++++++++------- go.mod | 2 +- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index c83a905aa5..373772d7c7 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -234,7 +234,9 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD return diag.FromErr(err) } - d.SetId(fmt.Sprintf("%s/%s", repo, file)) + branch := d.Get("branch").(string) + + d.SetId(fmt.Sprintf("%s/%s:%s", repo, file, branch)) if err = d.Set("commit_sha", create.GetSHA()); err != nil { return diag.FromErr(err) } @@ -484,7 +486,9 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD return nil, fmt.Errorf("file %s is not a file in repository %s/%s or repository is not readable", file, owner, repo) } - d.SetId(fmt.Sprintf("%s/%s", repo, file)) + branch := d.Get("branch").(string) + + d.SetId(fmt.Sprintf("%s/%s:%s", repo, file, branch)) if err = d.Set("overwrite_on_create", false); err != nil { return nil, err } diff --git a/github/resource_github_repository_file_migration.go b/github/resource_github_repository_file_migration.go index 5216702d1b..625be792af 100644 --- a/github/resource_github_repository_file_migration.go +++ b/github/resource_github_repository_file_migration.go @@ -108,6 +108,8 @@ func resourceGithubRepositoryFileStateUpgradeV0(ctx context.Context, rawState ma rawState["branch"] = repo.GetDefaultBranch() } + rawState["id"] = fmt.Sprintf("%s/%s:%s", rawState["repository"], rawState["file"], rawState["branch"]) + tflog.Debug(ctx, "GitHub Repository File State after migration", map[string]any{ "rawState": rawState, }) diff --git a/github/resource_github_repository_file_migration_test.go b/github/resource_github_repository_file_migration_test.go index e824c43d6e..4cca73ae18 100644 --- a/github/resource_github_repository_file_migration_test.go +++ b/github/resource_github_repository_file_migration_test.go @@ -2,8 +2,9 @@ package github import ( "context" - "reflect" "testing" + + "github.com/google/go-cmp/cmp" ) func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { @@ -28,7 +29,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { "overwrite_on_create": false, }, want: map[string]any{ - "id": "test-repo/path/to/file.txt", + "id": "test-repo/path/to/file.txt:main", "repository": "test-repo", "file": "path/to/file.txt", "content": "file content", @@ -49,7 +50,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { "branch": "develop", }, want: map[string]any{ - "id": "test-repo/README.md", + "id": "test-repo/README.md:develop", "repository": "test-repo", "file": "README.md", "content": "# README", @@ -67,7 +68,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { // "content": "file content", // }, // want: map[string]any{ - // "id": "test-repo/path/to/file.txt", + // "id": "test-repo/path/to/file.txt:main", // "repository": "test-repo", // "file": "path/to/file.txt", // "content": "file content", @@ -86,7 +87,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { // "branch": "", // }, // want: map[string]any{ - // "id": "test-repo/path/to/file.txt", + // "id": "test-repo/path/to/file.txt:main", // "repository": "test-repo", // "file": "path/to/file.txt", // "content": "file content", @@ -103,8 +104,8 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { t.Fatalf("unexpected error state: got error %v, shouldError %v", err, d.shouldError) } - if !d.shouldError && !reflect.DeepEqual(got, d.want) { - t.Fatalf("got %+v, want %+v", got, d.want) + if diff := cmp.Diff(got, d.want); diff != "" && !d.shouldError { + t.Fatalf("got %+v, want %+v, diff %s", got, d.want, diff) } }) } diff --git a/go.mod b/go.mod index 63b7d23f87..f1ba41382d 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.24.4 require ( github.com/go-jose/go-jose/v3 v3.0.4 + github.com/google/go-cmp v0.7.0 github.com/google/go-github/v82 v82.0.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-cty v1.5.0 @@ -21,7 +22,6 @@ require ( github.com/cloudflare/circl v1.6.1 // indirect github.com/fatih/color v1.18.0 // indirect github.com/golang/protobuf v1.5.4 // indirect - github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-querystring v1.2.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect From 3c2e59003b1e98e733f985c71ec8c737477b1ff8 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Mon, 9 Feb 2026 22:15:34 +0200 Subject: [PATCH 07/19] Fix ID parsing Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 373772d7c7..7590fc3a32 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -248,7 +248,11 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat client := meta.(*Owner).v3client owner := meta.(*Owner).name - repo, file := splitRepoFilePath(d.Id()) + repoFilePath, _, err := parseID2(d.Id()) + if err != nil { + return diag.FromErr(err) + } + repo, file := splitRepoFilePath(repoFilePath) ctx = tflog.SetField(ctx, "repository", repo) ctx = tflog.SetField(ctx, "file", file) ctx = tflog.SetField(ctx, "owner", owner) From e75070b453a08e03a11ecc31e7a8276d0561adce Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Feb 2026 11:31:35 +0200 Subject: [PATCH 08/19] fixup! Fix ID parsing Always use 2 part ID for import. Use buildID for resource ID --- github/resource_github_repository_file.go | 33 ++++++++++--------- ...source_github_repository_file_migration.go | 6 +++- ...e_github_repository_file_migration_test.go | 8 ++--- .../resource_github_repository_file_test.go | 1 + website/docs/r/repository_file.html.markdown | 10 ++++-- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 7590fc3a32..54fac629bd 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -6,7 +6,6 @@ import ( "fmt" "net/http" "net/url" - "strings" "github.com/google/go-github/v82/github" "github.com/hashicorp/terraform-plugin-log/tflog" @@ -236,7 +235,11 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD branch := d.Get("branch").(string) - d.SetId(fmt.Sprintf("%s/%s:%s", repo, file, branch)) + newResourceID, err := buildID(repo, file, branch) + if err != nil { + return diag.FromErr(err) + } + d.SetId(newResourceID) if err = d.Set("commit_sha", create.GetSHA()); err != nil { return diag.FromErr(err) } @@ -248,11 +251,11 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat client := meta.(*Owner).v3client owner := meta.(*Owner).name - repoFilePath, _, err := parseID2(d.Id()) + repo, file, _, err := parseID3(d.Id()) if err != nil { return diag.FromErr(err) } - repo, file := splitRepoFilePath(repoFilePath) + ctx = tflog.SetField(ctx, "repository", repo) ctx = tflog.SetField(ctx, "file", file) ctx = tflog.SetField(ctx, "owner", owner) @@ -452,12 +455,10 @@ func autoBranchDiffSuppressFunc(k, _, _ string, d *schema.ResourceData) bool { } func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { - importIDParts := strings.Split(d.Id(), idSeparator) - - if len(importIDParts) > 2 { - return nil, fmt.Errorf("invalid ID specified. Supplied ID must be written as / (when branch is \"main\") or /:") + repoFilePath, branch, err := parseID2(d.Id()) + if err != nil { + return nil, fmt.Errorf("invalid ID specified. Supplied ID must be written as /: (when branch is default) or /:. %w", err) } - repoFilePath := importIDParts[0] client := meta.(*Owner).v3client owner := meta.(*Owner).name @@ -465,8 +466,7 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD opts := &github.RepositoryContentGetOptions{} - if len(importIDParts) == 2 { - branch := importIDParts[1] + if branch != "" { opts.Ref = branch if err := d.Set("branch", branch); err != nil { return nil, err @@ -477,7 +477,8 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD return nil, err } defaultBranch := repoInfo.GetDefaultBranch() - if err := d.Set("branch", defaultBranch); err != nil { + branch = defaultBranch + if err := d.Set("branch", branch); err != nil { return nil, err } } @@ -490,9 +491,11 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD return nil, fmt.Errorf("file %s is not a file in repository %s/%s or repository is not readable", file, owner, repo) } - branch := d.Get("branch").(string) - - d.SetId(fmt.Sprintf("%s/%s:%s", repo, file, branch)) + newResourceID, err := buildID(repo, file, branch) + if err != nil { + return nil, err + } + d.SetId(newResourceID) if err = d.Set("overwrite_on_create", false); err != nil { return nil, err } diff --git a/github/resource_github_repository_file_migration.go b/github/resource_github_repository_file_migration.go index 625be792af..910c941a66 100644 --- a/github/resource_github_repository_file_migration.go +++ b/github/resource_github_repository_file_migration.go @@ -108,7 +108,11 @@ func resourceGithubRepositoryFileStateUpgradeV0(ctx context.Context, rawState ma rawState["branch"] = repo.GetDefaultBranch() } - rawState["id"] = fmt.Sprintf("%s/%s:%s", rawState["repository"], rawState["file"], rawState["branch"]) + newResourceID, err := buildID(rawState["repository"].(string), rawState["file"].(string), rawState["branch"].(string)) + if err != nil { + return nil, fmt.Errorf("failed to build ID: %w", err) + } + rawState["id"] = newResourceID tflog.Debug(ctx, "GitHub Repository File State after migration", map[string]any{ "rawState": rawState, diff --git a/github/resource_github_repository_file_migration_test.go b/github/resource_github_repository_file_migration_test.go index 4cca73ae18..bb3178726b 100644 --- a/github/resource_github_repository_file_migration_test.go +++ b/github/resource_github_repository_file_migration_test.go @@ -29,7 +29,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { "overwrite_on_create": false, }, want: map[string]any{ - "id": "test-repo/path/to/file.txt:main", + "id": "test-repo:path/to/file.txt:main", "repository": "test-repo", "file": "path/to/file.txt", "content": "file content", @@ -50,7 +50,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { "branch": "develop", }, want: map[string]any{ - "id": "test-repo/README.md:develop", + "id": "test-repo:README.md:develop", "repository": "test-repo", "file": "README.md", "content": "# README", @@ -68,7 +68,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { // "content": "file content", // }, // want: map[string]any{ - // "id": "test-repo/path/to/file.txt:main", + // "id": "test-repo:path/to/file.txt:main", // "repository": "test-repo", // "file": "path/to/file.txt", // "content": "file content", @@ -87,7 +87,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { // "branch": "", // }, // want: map[string]any{ - // "id": "test-repo/path/to/file.txt:main", + // "id": "test-repo:path/to/file.txt:main", // "repository": "test-repo", // "file": "path/to/file.txt", // "content": "file content", diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index c984cb7a70..5115b07cf4 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -460,6 +460,7 @@ func TestAccGithubRepositoryFile(t *testing.T) { ResourceName: "github_repository_file.test", ImportState: true, ImportStateVerify: true, + ImportStateId: fmt.Sprintf("%s/%s:", repoName, "test"), ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. }, }, diff --git a/website/docs/r/repository_file.html.markdown b/website/docs/r/repository_file.html.markdown index cc1a70487b..68cb7f0498 100644 --- a/website/docs/r/repository_file.html.markdown +++ b/website/docs/r/repository_file.html.markdown @@ -98,8 +98,14 @@ The following additional attributes are exported: ## Import -Repository files can be imported using a combination of the `repo`, `file` and `branch`, e.g. +Repository files can be imported using a combination of the `repo`, `file` and `branch` or empty branch for the default branch, e.g. ```sh -terraform import github_repository_file.gitignore example/.gitignore:main +terraform import github_repository_file.gitignore example/.gitignore:feature-branch +``` + +and using default branch: + +```sh +terraform import github_repository_file.gitignore example/.gitignore: ``` From 581f6843f1404848da77b45c41b305a3c5a17f37 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Feb 2026 20:53:02 +0200 Subject: [PATCH 09/19] fixup! fixup! Fix ID parsing Use 3 part ID for import as well --- github/resource_github_repository_file.go | 11 +++++------ github/resource_github_repository_file_test.go | 4 ++-- github/util.go | 5 ----- website/docs/r/repository_file.html.markdown | 4 ++-- 4 files changed, 9 insertions(+), 15 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 54fac629bd..fa7df9bf24 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -455,14 +455,13 @@ func autoBranchDiffSuppressFunc(k, _, _ string, d *schema.ResourceData) bool { } func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { - repoFilePath, branch, err := parseID2(d.Id()) + repo, filePath, branch, err := parseID3(d.Id()) if err != nil { - return nil, fmt.Errorf("invalid ID specified. Supplied ID must be written as /: (when branch is default) or /:. %w", err) + return nil, fmt.Errorf("invalid ID specified. Supplied ID must be written as :: (when branch is default) or ::. %w", err) } client := meta.(*Owner).v3client owner := meta.(*Owner).name - repo, file := splitRepoFilePath(repoFilePath) opts := &github.RepositoryContentGetOptions{} @@ -483,15 +482,15 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD } } - fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, file, opts) + fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, filePath, opts) if err != nil { return nil, err } if fc == nil { - return nil, fmt.Errorf("file %s is not a file in repository %s/%s or repository is not readable", file, owner, repo) + return nil, fmt.Errorf("filePath %s is not a file in repository %s/%s or repository is not readable", filePath, owner, repo) } - newResourceID, err := buildID(repo, file, branch) + newResourceID, err := buildID(repo, filePath, branch) if err != nil { return nil, err } diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index 5115b07cf4..d24a12afab 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -460,7 +460,7 @@ func TestAccGithubRepositoryFile(t *testing.T) { ResourceName: "github_repository_file.test", ImportState: true, ImportStateVerify: true, - ImportStateId: fmt.Sprintf("%s/%s:", repoName, "test"), + ImportStateId: fmt.Sprintf("%s:%s:", repoName, "test"), ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. }, }, @@ -526,7 +526,7 @@ func TestAccGithubRepositoryFile(t *testing.T) { ResourceName: "github_repository_file.test", ImportState: true, ImportStateVerify: true, - ImportStateId: fmt.Sprintf("%s/%s:main", repoName, "test"), + ImportStateId: fmt.Sprintf("%s:%s:main", repoName, "test"), ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. }, }, diff --git a/github/util.go b/github/util.go index e277299715..559f999e80 100644 --- a/github/util.go +++ b/github/util.go @@ -242,11 +242,6 @@ func (e *unconvertibleIdError) Error() string { e.OriginalId, e.OriginalError.Error()) } -func splitRepoFilePath(path string) (string, string) { - parts := strings.Split(path, "/") - return parts[0], strings.Join(parts[1:], "/") -} - func getTeamID(teamIDString string, meta any) (int64, error) { // Given a string that is either a team id or team slug, return the // id of the team it is referring to. diff --git a/website/docs/r/repository_file.html.markdown b/website/docs/r/repository_file.html.markdown index 68cb7f0498..c67eec0784 100644 --- a/website/docs/r/repository_file.html.markdown +++ b/website/docs/r/repository_file.html.markdown @@ -101,11 +101,11 @@ The following additional attributes are exported: Repository files can be imported using a combination of the `repo`, `file` and `branch` or empty branch for the default branch, e.g. ```sh -terraform import github_repository_file.gitignore example/.gitignore:feature-branch +terraform import github_repository_file.gitignore example:.gitignore:feature-branch ``` and using default branch: ```sh -terraform import github_repository_file.gitignore example/.gitignore: +terraform import github_repository_file.gitignore example:.gitignore: ``` From 9b9f8b848b098641977b02867be705eff58c0184 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Feb 2026 21:29:01 +0200 Subject: [PATCH 10/19] fixup! fixup! fixup! Add computed `repository_id` field to resource Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 20 ++- .../resource_github_repository_file_test.go | 134 +++++------------- 2 files changed, 55 insertions(+), 99 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index fa7df9bf24..c42b22543d 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -38,9 +38,13 @@ func resourceGithubRepositoryFile() *schema.Resource { "repository": { Type: schema.TypeString, Required: true, - ForceNew: true, Description: "The repository name", }, + "repository_id": { + Type: schema.TypeInt, + Computed: true, + Description: "The repository ID", + }, "file": { Type: schema.TypeString, Required: true, @@ -125,6 +129,7 @@ func resourceGithubRepositoryFile() *schema.Resource { DiffSuppressFunc: autoBranchDiffSuppressFunc, }, }, + CustomizeDiff: diffRepository, } } @@ -171,6 +176,8 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD checkOpt := github.RepositoryContentGetOptions{} + repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if branch, ok := d.GetOk("branch"); ok { tflog.Debug(ctx, "Using explicitly set branch", map[string]any{ "branch": branch.(string), @@ -186,7 +193,6 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD } checkOpt.Ref = branch.(string) } else { - repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) if err != nil { return diag.FromErr(err) } @@ -195,6 +201,10 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD } } + if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { + return diag.FromErr(err) + } + opts := resourceGithubRepositoryFileOptions(d) if opts.Message == nil { @@ -465,13 +475,14 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD opts := &github.RepositoryContentGetOptions{} + repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) if branch != "" { opts.Ref = branch if err := d.Set("branch", branch); err != nil { return nil, err } } else { - repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if err != nil { return nil, err } @@ -481,6 +492,9 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD return nil, err } } + if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { + return nil, err + } fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, filePath, opts) if err != nil { diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index d24a12afab..979f3f7043 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -272,7 +272,7 @@ func TestAccGithubRepositoryFile(t *testing.T) { t.Run("creates and manages files on auto created branch if branch does not exist", func(t *testing.T) { randomID := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum) repoName := fmt.Sprintf("%srepo-file-%s", testResourcePrefix, randomID) - config := fmt.Sprintf(` + config := ` resource "github_repository" "test" { name = "%s" auto_init = true @@ -287,53 +287,33 @@ func TestAccGithubRepositoryFile(t *testing.T) { commit_message = "Managed by Terraform" commit_author = "Terraform User" commit_email = "terraform@example.com" - autocreate_branch = false + autocreate_branch = %t } - `, repoName) - - check := resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "github_repository_file.test", "content", - "bar", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "sha", - "ba0e162e1c47469e3fe4b393a8bf8c569f302116", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "ref", - "does/not/exist", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_author", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_email", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_message", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_sha", - ), - resource.TestCheckResourceAttr("github_repository_file.test", "autocreate_branch", "true"), - resource.TestCheckResourceAttr("github_repository_file.test", "autocreate_branch_source_branch", "main"), - resource.TestCheckResourceAttrSet("github_repository_file.test", "autocreate_branch_source_sha"), - ) + ` resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ { - Config: config, + Config: fmt.Sprintf(config, repoName, false), ExpectError: regexp.MustCompile(`unexpected status code: 404 Not Found`), }, { - Config: strings.Replace(config, - "autocreate_branch = false", - "autocreate_branch = true", 1), - Check: check, + Config: fmt.Sprintf(config, repoName, true), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("github_repository_file.test", "content", "bar"), + resource.TestCheckResourceAttr("github_repository_file.test", "sha", "ba0e162e1c47469e3fe4b393a8bf8c569f302116"), + resource.TestCheckResourceAttr("github_repository_file.test", "ref", "does/not/exist"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_author"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_email"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_message"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_sha"), + resource.TestCheckResourceAttr("github_repository_file.test", "autocreate_branch", "true"), + resource.TestCheckResourceAttr("github_repository_file.test", "autocreate_branch_source_branch", "main"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "autocreate_branch_source_sha"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "repository_id"), + ), }, }, }) @@ -371,19 +351,13 @@ func TestAccGithubRepositoryFile(t *testing.T) { { Config: config, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "github_repository_file.test", "file", - "archived-test.md", - ), + resource.TestCheckResourceAttr("github_repository_file.test", "file", "archived-test.md"), ), }, { Config: archivedConfig, Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "github_repository.test", "archived", - "true", - ), + resource.TestCheckResourceAttr("github_repository.test", "archived", "true"), ), }, // This step should succeed - the file should be removed from state @@ -426,34 +400,18 @@ func TestAccGithubRepositoryFile(t *testing.T) { Steps: []resource.TestStep{ { Config: config, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "github_repository_file.test", "content", - "bar", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "sha", - "ba0e162e1c47469e3fe4b393a8bf8c569f302116", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "ref", - "main", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_author", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_email", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_message", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_sha", - ), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("github_repository_file.test", "content", "bar"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "sha"), + resource.TestCheckResourceAttr("github_repository_file.test", "ref", "main"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_author"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_email"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_message"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_sha"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_branch"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_sha"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "repository_id"), ), }, { @@ -492,34 +450,18 @@ func TestAccGithubRepositoryFile(t *testing.T) { Steps: []resource.TestStep{ { Config: config, - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "github_repository_file.test", "content", - "bar", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "sha", - "ba0e162e1c47469e3fe4b393a8bf8c569f302116", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "ref", - "main", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_author", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_email", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_message", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_sha", - ), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("github_repository_file.test", "content", "bar"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "sha"), + resource.TestCheckResourceAttr("github_repository_file.test", "ref", "main"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_author"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_email"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_message"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_sha"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_branch"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_sha"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "repository_id"), ), }, { From 46162f6dc5678e81953b91a854e86cd5a42983b6 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Feb 2026 21:32:57 +0200 Subject: [PATCH 11/19] fixup! fixup! fixup! fixup! Add migration of the `repository_id` field. This required changing all tests to need a mock of the GH API Signed-off-by: Timo Sand --- ...source_github_repository_file_migration.go | 28 ++-- ...e_github_repository_file_migration_test.go | 127 ++++++++++++------ 2 files changed, 99 insertions(+), 56 deletions(-) diff --git a/github/resource_github_repository_file_migration.go b/github/resource_github_repository_file_migration.go index 910c941a66..1c6739e58d 100644 --- a/github/resource_github_repository_file_migration.go +++ b/github/resource_github_repository_file_migration.go @@ -89,22 +89,24 @@ func resourceGithubRepositoryFileStateUpgradeV0(ctx context.Context, rawState ma "rawState": rawState, }) - // If branch is missing or empty, fetch the default branch from the repository - if branch, ok := rawState["branch"].(string); !ok || branch == "" { - meta := m.(*Owner) - client := meta.v3client - owner := meta.name + meta := m.(*Owner) + client := meta.v3client + owner := meta.name + + repoName, ok := rawState["repository"].(string) + if !ok { + return nil, fmt.Errorf("repository not found or is not a string") + } - repoName, ok := rawState["repository"].(string) - if !ok { - return nil, fmt.Errorf("repository not found or is not a string") - } + repo, _, err := client.Repositories.Get(ctx, owner, repoName) + if err != nil { + return nil, fmt.Errorf("failed to retrieve repository '%s': %w", repoName, err) + } - repo, _, err := client.Repositories.Get(ctx, owner, repoName) - if err != nil { - return nil, fmt.Errorf("failed to retrieve repository %s: %w", repoName, err) - } + rawState["repository_id"] = int(repo.GetID()) + // If branch is missing or empty, fetch the default branch from the repository + if branch, ok := rawState["branch"].(string); !ok || branch == "" { rawState["branch"] = repo.GetDefaultBranch() } diff --git a/github/resource_github_repository_file_migration_test.go b/github/resource_github_repository_file_migration_test.go index bb3178726b..ac330c5054 100644 --- a/github/resource_github_repository_file_migration_test.go +++ b/github/resource_github_repository_file_migration_test.go @@ -2,12 +2,36 @@ package github import ( "context" + "encoding/json" + "fmt" + "net/http" + "net/url" "testing" "github.com/google/go-cmp/cmp" + "github.com/google/go-github/v82/github" ) -func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { +func buildMockResponsesForRepositoryFileMigrationV0toV1(mockOwner, mockRepo string, wantRepoID int) []*mockResponse { + responseBodyJson, err := json.Marshal(github.Repository{ + ID: github.Ptr(int64(wantRepoID)), + DefaultBranch: github.Ptr("main"), + Name: github.Ptr(mockRepo), + }) + if err != nil { + panic(fmt.Sprintf("error marshalling repository response: %s", err)) + } + return []*mockResponse{{ + ExpectedUri: fmt.Sprintf("/repos/%s/%s", mockOwner, mockRepo), + ExpectedHeaders: map[string]string{ + "Accept": "application/vnd.github.scarlet-witch-preview+json, application/vnd.github.mercy-preview+json, application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json", + }, + ResponseBody: string(responseBodyJson), + StatusCode: http.StatusOK, + }} +} + +func Test_resourceGithubRepositoryFileStateUpgradeV0toV1(t *testing.T) { t.Parallel() for _, d := range []struct { @@ -31,6 +55,7 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { want: map[string]any{ "id": "test-repo:path/to/file.txt:main", "repository": "test-repo", + "repository_id": 1234567890, "file": "path/to/file.txt", "content": "file content", "branch": "main", @@ -50,56 +75,72 @@ func Test_resourceGithubRepositoryFileStateUpgradeV0(t *testing.T) { "branch": "develop", }, want: map[string]any{ - "id": "test-repo:README.md:develop", + "id": "test-repo:README.md:develop", + "repository": "test-repo", + "repository_id": 1234567890, + "file": "README.md", + "content": "# README", + "branch": "develop", + }, + shouldError: false, + }, + { + testName: "migrates_with_missing_branch", + rawState: map[string]any{ + "id": "test-repo/path/to/file.txt", "repository": "test-repo", - "file": "README.md", - "content": "# README", - "branch": "develop", + "file": "path/to/file.txt", + "content": "file content", + }, + want: map[string]any{ + "id": "test-repo:path/to/file.txt:main", + "repository": "test-repo", + "repository_id": 1234567890, + "file": "path/to/file.txt", + "content": "file content", + "branch": "main", // fetched from API + }, + shouldError: false, + }, + { + testName: "migrates_with_empty_branch", + rawState: map[string]any{ + "id": "test-repo/path/to/file.txt", + "repository": "test-repo", + "file": "path/to/file.txt", + "content": "file content", + "branch": "", + }, + want: map[string]any{ + "id": "test-repo:path/to/file.txt:main", + "repository": "test-repo", + "repository_id": 1234567890, + "file": "path/to/file.txt", + "content": "file content", + "branch": "main", // fetched from API }, shouldError: false, }, - // TODO: Enable this test once we have a pattern to create a mock client for the test. - // { - // testName: "migrates_with_missing_branch", - // rawState: map[string]any{ - // "id": "test-repo/path/to/file.txt", - // "repository": "test-repo", - // "file": "path/to/file.txt", - // "content": "file content", - // }, - // want: map[string]any{ - // "id": "test-repo:path/to/file.txt:main", - // "repository": "test-repo", - // "file": "path/to/file.txt", - // "content": "file content", - // "branch": "main", // fetched from API - // }, - // shouldError: false, - // }, - // TODO: Enable this test once we have a pattern to create a mock client for the test. - // { - // testName: "migrates_with_empty_branch", - // rawState: map[string]any{ - // "id": "test-repo/path/to/file.txt", - // "repository": "test-repo", - // "file": "path/to/file.txt", - // "content": "file content", - // "branch": "", - // }, - // want: map[string]any{ - // "id": "test-repo:path/to/file.txt:main", - // "repository": "test-repo", - // "file": "path/to/file.txt", - // "content": "file content", - // "branch": "main", // fetched from API - // }, - // shouldError: false, - // }, } { t.Run(d.testName, func(t *testing.T) { t.Parallel() - got, err := resourceGithubRepositoryFileStateUpgradeV0(context.Background(), d.rawState, nil) + meta := &Owner{ + name: "test-org", + } + + ts := githubApiMock(buildMockResponsesForRepositoryFileMigrationV0toV1(meta.name, d.want["repository"].(string), d.want["repository_id"].(int))) + defer ts.Close() + + httpCl := http.DefaultClient + httpCl.Transport = http.DefaultTransport + + client := github.NewClient(httpCl) + u, _ := url.Parse(ts.URL + "/") + client.BaseURL = u + meta.v3client = client + + got, err := resourceGithubRepositoryFileStateUpgradeV0(context.Background(), d.rawState, meta) if (err != nil) != d.shouldError { t.Fatalf("unexpected error state: got error %v, shouldError %v", err, d.shouldError) } From 08a8c4c4952726f62b1ab615ef88bd0535af1ef3 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Feb 2026 22:33:31 +0200 Subject: [PATCH 12/19] Comment out test in evaluation Signed-off-by: Timo Sand --- ...e_github_repository_file_migration_test.go | 286 +++++++++--------- 1 file changed, 144 insertions(+), 142 deletions(-) diff --git a/github/resource_github_repository_file_migration_test.go b/github/resource_github_repository_file_migration_test.go index ac330c5054..6d2c59ad02 100644 --- a/github/resource_github_repository_file_migration_test.go +++ b/github/resource_github_repository_file_migration_test.go @@ -1,153 +1,155 @@ -package github +// TODO: Enable this test once we have a way to mock the GitHub API -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "net/url" - "testing" +// package github - "github.com/google/go-cmp/cmp" - "github.com/google/go-github/v82/github" -) +// import ( +// "context" +// "encoding/json" +// "fmt" +// "net/http" +// "net/url" +// "testing" -func buildMockResponsesForRepositoryFileMigrationV0toV1(mockOwner, mockRepo string, wantRepoID int) []*mockResponse { - responseBodyJson, err := json.Marshal(github.Repository{ - ID: github.Ptr(int64(wantRepoID)), - DefaultBranch: github.Ptr("main"), - Name: github.Ptr(mockRepo), - }) - if err != nil { - panic(fmt.Sprintf("error marshalling repository response: %s", err)) - } - return []*mockResponse{{ - ExpectedUri: fmt.Sprintf("/repos/%s/%s", mockOwner, mockRepo), - ExpectedHeaders: map[string]string{ - "Accept": "application/vnd.github.scarlet-witch-preview+json, application/vnd.github.mercy-preview+json, application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json", - }, - ResponseBody: string(responseBodyJson), - StatusCode: http.StatusOK, - }} -} +// "github.com/google/go-cmp/cmp" +// "github.com/google/go-github/v82/github" +// ) -func Test_resourceGithubRepositoryFileStateUpgradeV0toV1(t *testing.T) { - t.Parallel() +// func buildMockResponsesForRepositoryFileMigrationV0toV1(mockOwner, mockRepo string, wantRepoID int) []*mockResponse { +// responseBodyJson, err := json.Marshal(github.Repository{ +// ID: github.Ptr(int64(wantRepoID)), +// DefaultBranch: github.Ptr("main"), +// Name: github.Ptr(mockRepo), +// }) +// if err != nil { +// panic(fmt.Sprintf("error marshalling repository response: %s", err)) +// } +// return []*mockResponse{{ +// ExpectedUri: fmt.Sprintf("/repos/%s/%s", mockOwner, mockRepo), +// ExpectedHeaders: map[string]string{ +// "Accept": "application/vnd.github.scarlet-witch-preview+json, application/vnd.github.mercy-preview+json, application/vnd.github.baptiste-preview+json, application/vnd.github.nebula-preview+json", +// }, +// ResponseBody: string(responseBodyJson), +// StatusCode: http.StatusOK, +// }} +// } - for _, d := range []struct { - testName string - rawState map[string]any - want map[string]any - shouldError bool - }{ - { - testName: "preserves_existing_branch", - rawState: map[string]any{ - "id": "test-repo/path/to/file.txt", - "repository": "test-repo", - "file": "path/to/file.txt", - "content": "file content", - "branch": "main", - "commit_sha": "abc123", - "sha": "def456", - "overwrite_on_create": false, - }, - want: map[string]any{ - "id": "test-repo:path/to/file.txt:main", - "repository": "test-repo", - "repository_id": 1234567890, - "file": "path/to/file.txt", - "content": "file content", - "branch": "main", - "commit_sha": "abc123", - "sha": "def456", - "overwrite_on_create": false, - }, - shouldError: false, - }, - { - testName: "preserves_custom_branch", - rawState: map[string]any{ - "id": "test-repo/README.md", - "repository": "test-repo", - "file": "README.md", - "content": "# README", - "branch": "develop", - }, - want: map[string]any{ - "id": "test-repo:README.md:develop", - "repository": "test-repo", - "repository_id": 1234567890, - "file": "README.md", - "content": "# README", - "branch": "develop", - }, - shouldError: false, - }, - { - testName: "migrates_with_missing_branch", - rawState: map[string]any{ - "id": "test-repo/path/to/file.txt", - "repository": "test-repo", - "file": "path/to/file.txt", - "content": "file content", - }, - want: map[string]any{ - "id": "test-repo:path/to/file.txt:main", - "repository": "test-repo", - "repository_id": 1234567890, - "file": "path/to/file.txt", - "content": "file content", - "branch": "main", // fetched from API - }, - shouldError: false, - }, - { - testName: "migrates_with_empty_branch", - rawState: map[string]any{ - "id": "test-repo/path/to/file.txt", - "repository": "test-repo", - "file": "path/to/file.txt", - "content": "file content", - "branch": "", - }, - want: map[string]any{ - "id": "test-repo:path/to/file.txt:main", - "repository": "test-repo", - "repository_id": 1234567890, - "file": "path/to/file.txt", - "content": "file content", - "branch": "main", // fetched from API - }, - shouldError: false, - }, - } { - t.Run(d.testName, func(t *testing.T) { - t.Parallel() +// func Test_resourceGithubRepositoryFileStateUpgradeV0toV1(t *testing.T) { +// t.Parallel() - meta := &Owner{ - name: "test-org", - } +// for _, d := range []struct { +// testName string +// rawState map[string]any +// want map[string]any +// shouldError bool +// }{ +// { +// testName: "preserves_existing_branch", +// rawState: map[string]any{ +// "id": "test-repo/path/to/file.txt", +// "repository": "test-repo", +// "file": "path/to/file.txt", +// "content": "file content", +// "branch": "main", +// "commit_sha": "abc123", +// "sha": "def456", +// "overwrite_on_create": false, +// }, +// want: map[string]any{ +// "id": "test-repo:path/to/file.txt:main", +// "repository": "test-repo", +// "repository_id": 1234567890, +// "file": "path/to/file.txt", +// "content": "file content", +// "branch": "main", +// "commit_sha": "abc123", +// "sha": "def456", +// "overwrite_on_create": false, +// }, +// shouldError: false, +// }, +// { +// testName: "preserves_custom_branch", +// rawState: map[string]any{ +// "id": "test-repo/README.md", +// "repository": "test-repo", +// "file": "README.md", +// "content": "# README", +// "branch": "develop", +// }, +// want: map[string]any{ +// "id": "test-repo:README.md:develop", +// "repository": "test-repo", +// "repository_id": 1234567890, +// "file": "README.md", +// "content": "# README", +// "branch": "develop", +// }, +// shouldError: false, +// }, +// { +// testName: "migrates_with_missing_branch", +// rawState: map[string]any{ +// "id": "test-repo/path/to/file.txt", +// "repository": "test-repo", +// "file": "path/to/file.txt", +// "content": "file content", +// }, +// want: map[string]any{ +// "id": "test-repo:path/to/file.txt:main", +// "repository": "test-repo", +// "repository_id": 1234567890, +// "file": "path/to/file.txt", +// "content": "file content", +// "branch": "main", // fetched from API +// }, +// shouldError: false, +// }, +// { +// testName: "migrates_with_empty_branch", +// rawState: map[string]any{ +// "id": "test-repo/path/to/file.txt", +// "repository": "test-repo", +// "file": "path/to/file.txt", +// "content": "file content", +// "branch": "", +// }, +// want: map[string]any{ +// "id": "test-repo:path/to/file.txt:main", +// "repository": "test-repo", +// "repository_id": 1234567890, +// "file": "path/to/file.txt", +// "content": "file content", +// "branch": "main", // fetched from API +// }, +// shouldError: false, +// }, +// } { +// t.Run(d.testName, func(t *testing.T) { +// t.Parallel() - ts := githubApiMock(buildMockResponsesForRepositoryFileMigrationV0toV1(meta.name, d.want["repository"].(string), d.want["repository_id"].(int))) - defer ts.Close() +// meta := &Owner{ +// name: "test-org", +// } - httpCl := http.DefaultClient - httpCl.Transport = http.DefaultTransport +// ts := githubApiMock(buildMockResponsesForRepositoryFileMigrationV0toV1(meta.name, d.want["repository"].(string), d.want["repository_id"].(int))) +// defer ts.Close() - client := github.NewClient(httpCl) - u, _ := url.Parse(ts.URL + "/") - client.BaseURL = u - meta.v3client = client +// httpCl := http.DefaultClient +// httpCl.Transport = http.DefaultTransport - got, err := resourceGithubRepositoryFileStateUpgradeV0(context.Background(), d.rawState, meta) - if (err != nil) != d.shouldError { - t.Fatalf("unexpected error state: got error %v, shouldError %v", err, d.shouldError) - } +// client := github.NewClient(httpCl) +// u, _ := url.Parse(ts.URL + "/") +// client.BaseURL = u +// meta.v3client = client - if diff := cmp.Diff(got, d.want); diff != "" && !d.shouldError { - t.Fatalf("got %+v, want %+v, diff %s", got, d.want, diff) - } - }) - } -} +// got, err := resourceGithubRepositoryFileStateUpgradeV0(context.Background(), d.rawState, meta) +// if (err != nil) != d.shouldError { +// t.Fatalf("unexpected error state: got error %v, shouldError %v", err, d.shouldError) +// } + +// if diff := cmp.Diff(got, d.want); diff != "" && !d.shouldError { +// t.Fatalf("got %+v, want %+v, diff %s", got, d.want, diff) +// } +// }) +// } +// } From b07ed8410d07b959ce8bcf110c9e132b1ae7a132 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Tue, 10 Feb 2026 23:38:30 +0200 Subject: [PATCH 13/19] fixup! Address review comments Signed-off-by: Timo Sand --- github/repository_utils.go | 9 +- github/resource_github_repository_file.go | 127 +++++++++--------- ...e_github_repository_file_migration_test.go | 4 +- .../resource_github_repository_file_test.go | 2 - go.mod | 2 +- 5 files changed, 75 insertions(+), 69 deletions(-) diff --git a/github/repository_utils.go b/github/repository_utils.go index 00d6f3e23c..1c62465491 100644 --- a/github/repository_utils.go +++ b/github/repository_utils.go @@ -9,11 +9,16 @@ import ( "strings" "github.com/google/go-github/v82/github" + "github.com/hashicorp/terraform-plugin-log/tflog" ) // checkRepositoryBranchExists tests if a branch exists in a repository. -func checkRepositoryBranchExists(client *github.Client, owner, repo, branch string) error { - ctx := context.WithValue(context.Background(), ctxId, buildTwoPartID(repo, branch)) +func checkRepositoryBranchExists(ctx context.Context, client *github.Client, owner, repo, branch string) error { + tflog.Debug(ctx, "Checking if branch exists", map[string]any{ + "branch": branch, + "owner": owner, + "repo": repo, + }) _, _, err := client.Repositories.GetBranch(ctx, owner, repo, branch, 2) if err != nil { var ghErr *github.ErrorResponse diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index c42b22543d..757924ab70 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -177,12 +177,17 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD checkOpt := github.RepositoryContentGetOptions{} repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if err != nil { + return diag.FromErr(err) + } + var branch string - if branch, ok := d.GetOk("branch"); ok { + if branchFieldVal, ok := d.GetOk("branch"); ok { + branch = branchFieldVal.(string) tflog.Debug(ctx, "Using explicitly set branch", map[string]any{ - "branch": branch.(string), + "branch": branch, }) - if err := checkRepositoryBranchExists(client, owner, repo, branch.(string)); err != nil { + if err := checkRepositoryBranchExists(ctx, client, owner, repo, branch); err != nil { if d.Get("autocreate_branch").(bool) { if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { return diag.FromErr(err) @@ -191,14 +196,9 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD return diag.FromErr(err) } } - checkOpt.Ref = branch.(string) + checkOpt.Ref = branch } else { - if err != nil { - return diag.FromErr(err) - } - if err := d.Set("branch", repoInfo.GetDefaultBranch()); err != nil { - return diag.FromErr(err) - } + branch = repoInfo.GetDefaultBranch() } if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { @@ -243,12 +243,17 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD return diag.FromErr(err) } - branch := d.Get("branch").(string) + if err := d.Set("branch", branch); err != nil { + return diag.FromErr(err) + } newResourceID, err := buildID(repo, file, branch) if err != nil { return diag.FromErr(err) } + tflog.Debug(ctx, "Setting ID", map[string]any{ + "id": newResourceID, + }) d.SetId(newResourceID) if err = d.Set("commit_sha", create.GetSHA()); err != nil { return diag.FromErr(err) @@ -261,34 +266,34 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat client := meta.(*Owner).v3client owner := meta.(*Owner).name - repo, file, _, err := parseID3(d.Id()) - if err != nil { - return diag.FromErr(err) + repoName, ok := d.Get("repository").(string) + if !ok { + return diag.FromErr(fmt.Errorf("repository not found or is not a string")) + } + file, ok := d.Get("file").(string) + if !ok { + return diag.FromErr(fmt.Errorf("file not found or is not a string")) } - ctx = tflog.SetField(ctx, "repository", repo) + ctx = tflog.SetField(ctx, "repository", repoName) ctx = tflog.SetField(ctx, "file", file) ctx = tflog.SetField(ctx, "owner", owner) opts := &github.RepositoryContentGetOptions{} - if branch, ok := d.GetOk("branch"); ok { - tflog.Debug(ctx, "Using explicitly set branch", map[string]any{ - "branch": branch.(string), - }) - if err := checkRepositoryBranchExists(client, owner, repo, branch.(string)); err != nil { - if d.Get("autocreate_branch").(bool) { - branch = d.Get("autocreate_branch_source_branch").(string) - } else { - tflog.Info(ctx, "Removing repository path from state because the branch no longer exists in GitHub") - d.SetId("") - return nil - } + branch := d.Get("branch").(string) + if err := checkRepositoryBranchExists(ctx, client, owner, repoName, branch); err != nil { + if d.Get("autocreate_branch").(bool) { + branch = d.Get("autocreate_branch_source_branch").(string) + } else { + tflog.Info(ctx, "Removing repository path from state because the branch no longer exists in GitHub") + d.SetId("") + return nil } - opts.Ref = branch.(string) } + opts.Ref = branch - fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, file, opts) + fc, _, _, err := client.Repositories.GetContents(ctx, owner, repoName, file, opts) if err != nil { var errorResponse *github.ErrorResponse if errors.As(err, &errorResponse) && errorResponse.Response.StatusCode == http.StatusTooManyRequests { @@ -309,12 +314,7 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat if err = d.Set("content", content); err != nil { return diag.FromErr(err) } - if err = d.Set("repository", repo); err != nil { - return diag.FromErr(err) - } - if err = d.Set("file", file); err != nil { - return diag.FromErr(err) - } + if err = d.Set("sha", fc.GetSHA()); err != nil { return diag.FromErr(err) } @@ -339,10 +339,10 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat tflog.Debug(ctx, "Using known commit SHA", map[string]any{ "commit_sha": sha.(string), }) - commit, _, err = client.Repositories.GetCommit(ctx, owner, repo, sha.(string), nil) + commit, _, err = client.Repositories.GetCommit(ctx, owner, repoName, sha.(string), nil) } else { tflog.Debug(ctx, "Commit SHA unknown for file, looking for commit") - commit, err = getFileCommit(ctx, client, owner, repo, file, ref) + commit, err = getFileCommit(ctx, client, owner, repoName, file, ref) } if err != nil { return diag.FromErr(err) @@ -387,18 +387,15 @@ func resourceGithubRepositoryFileUpdate(ctx context.Context, d *schema.ResourceD ctx = tflog.SetField(ctx, "file", file) ctx = tflog.SetField(ctx, "owner", owner) - if branch, ok := d.GetOk("branch"); ok { - tflog.Debug(ctx, "Using explicitly set branch", map[string]any{ - "branch": branch.(string), - }) - if err := checkRepositoryBranchExists(client, owner, repo, branch.(string)); err != nil { - if d.Get("autocreate_branch").(bool) { - if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { - return diag.FromErr(err) - } - } else { + branch := d.Get("branch").(string) + + if err := checkRepositoryBranchExists(ctx, client, owner, repo, branch); err != nil { + if d.Get("autocreate_branch").(bool) { + if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { return diag.FromErr(err) } + } else { + return diag.FromErr(err) } } @@ -433,22 +430,18 @@ func resourceGithubRepositoryFileDelete(ctx context.Context, d *schema.ResourceD opts.Message = github.Ptr(fmt.Sprintf("Delete %s", file)) } - if b, ok := d.GetOk("branch"); ok { - tflog.Debug(ctx, "Using explicitly set branch", map[string]any{ - "branch": b.(string), - }) - if err := checkRepositoryBranchExists(client, owner, repo, b.(string)); err != nil { - if d.Get("autocreate_branch").(bool) { - if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { - return diag.FromErr(err) - } - } else { + branch := d.Get("branch").(string) + + if err := checkRepositoryBranchExists(ctx, client, owner, repo, branch); err != nil { + if d.Get("autocreate_branch").(bool) { + if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { return diag.FromErr(err) } + } else { + return diag.FromErr(err) } - branch := b.(string) - opts.Branch = github.Ptr(branch) } + opts.Branch = github.Ptr(branch) _, _, err := client.Repositories.DeleteFile(ctx, owner, repo, file, opts) return diag.FromErr(handleArchivedRepoDelete(err, "repository file", file, owner, repo)) @@ -476,6 +469,9 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD opts := &github.RepositoryContentGetOptions{} repoInfo, _, err := client.Repositories.Get(ctx, owner, repo) + if err != nil { + return nil, err + } if branch != "" { opts.Ref = branch if err := d.Set("branch", branch); err != nil { @@ -483,9 +479,6 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD } } else { - if err != nil { - return nil, err - } defaultBranch := repoInfo.GetDefaultBranch() branch = defaultBranch if err := d.Set("branch", branch); err != nil { @@ -504,10 +497,20 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD return nil, fmt.Errorf("filePath %s is not a file in repository %s/%s or repository is not readable", filePath, owner, repo) } + if err := d.Set("repository", repo); err != nil { + return nil, err + } + if err := d.Set("file", filePath); err != nil { + return nil, err + } + newResourceID, err := buildID(repo, filePath, branch) if err != nil { return nil, err } + tflog.Debug(ctx, "Setting ID", map[string]any{ + "id": newResourceID, + }) d.SetId(newResourceID) if err = d.Set("overwrite_on_create", false); err != nil { return nil, err diff --git a/github/resource_github_repository_file_migration_test.go b/github/resource_github_repository_file_migration_test.go index 6d2c59ad02..ba02db041f 100644 --- a/github/resource_github_repository_file_migration_test.go +++ b/github/resource_github_repository_file_migration_test.go @@ -1,6 +1,6 @@ -// TODO: Enable this test once we have a way to mock the GitHub API +package github -// package github +// TODO: Enable this test once we have a way to mock the GitHub API // import ( // "context" diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index 979f3f7043..7520403be8 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -418,7 +418,6 @@ func TestAccGithubRepositoryFile(t *testing.T) { ResourceName: "github_repository_file.test", ImportState: true, ImportStateVerify: true, - ImportStateId: fmt.Sprintf("%s:%s:", repoName, "test"), ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. }, }, @@ -468,7 +467,6 @@ func TestAccGithubRepositoryFile(t *testing.T) { ResourceName: "github_repository_file.test", ImportState: true, ImportStateVerify: true, - ImportStateId: fmt.Sprintf("%s:%s:main", repoName, "test"), ImportStateVerifyIgnore: []string{"commit_author", "commit_email"}, // For some reason `d` doesn't contain the commit author and email when importing. }, }, diff --git a/go.mod b/go.mod index f1ba41382d..63b7d23f87 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.24.4 require ( github.com/go-jose/go-jose/v3 v3.0.4 - github.com/google/go-cmp v0.7.0 github.com/google/go-github/v82 v82.0.0 github.com/google/uuid v1.6.0 github.com/hashicorp/go-cty v1.5.0 @@ -22,6 +21,7 @@ require ( github.com/cloudflare/circl v1.6.1 // indirect github.com/fatih/color v1.18.0 // indirect github.com/golang/protobuf v1.5.4 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/google/go-querystring v1.2.0 // indirect github.com/hashicorp/errwrap v1.0.0 // indirect github.com/hashicorp/go-checkpoint v0.5.0 // indirect From 5e43cb51601514fb86d0cea6ffbb51772b01e3c6 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 11 Feb 2026 05:45:17 +0200 Subject: [PATCH 14/19] fixup! Address review comments Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 64 +++++++++++------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 757924ab70..ec3dcefd45 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -201,10 +201,6 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD branch = repoInfo.GetDefaultBranch() } - if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { - return diag.FromErr(err) - } - opts := resourceGithubRepositoryFileOptions(d) if opts.Message == nil { @@ -243,10 +239,6 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD return diag.FromErr(err) } - if err := d.Set("branch", branch); err != nil { - return diag.FromErr(err) - } - newResourceID, err := buildID(repo, file, branch) if err != nil { return diag.FromErr(err) @@ -255,9 +247,17 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD "id": newResourceID, }) d.SetId(newResourceID) + + // Set computed values after the resource is created and in state if err = d.Set("commit_sha", create.GetSHA()); err != nil { return diag.FromErr(err) } + if err := d.Set("branch", branch); err != nil { + return diag.FromErr(err) + } + if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { + return diag.FromErr(err) + } return resourceGithubRepositoryFileRead(ctx, d, meta) } @@ -266,22 +266,17 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat client := meta.(*Owner).v3client owner := meta.(*Owner).name - repoName, ok := d.Get("repository").(string) - if !ok { - return diag.FromErr(fmt.Errorf("repository not found or is not a string")) - } - file, ok := d.Get("file").(string) - if !ok { - return diag.FromErr(fmt.Errorf("file not found or is not a string")) - } + repoName := d.Get("repository").(string) + file := d.Get("file").(string) + branch := d.Get("branch").(string) ctx = tflog.SetField(ctx, "repository", repoName) ctx = tflog.SetField(ctx, "file", file) ctx = tflog.SetField(ctx, "owner", owner) + ctx = tflog.SetField(ctx, "owner", owner) opts := &github.RepositoryContentGetOptions{} - branch := d.Get("branch").(string) if err := checkRepositoryBranchExists(ctx, client, owner, repoName, branch); err != nil { if d.Get("autocreate_branch").(bool) { branch = d.Get("autocreate_branch_source_branch").(string) @@ -405,6 +400,7 @@ func resourceGithubRepositoryFileUpdate(ctx context.Context, d *schema.ResourceD opts.Message = github.Ptr(fmt.Sprintf("Update %s", file)) } + // TODO: Use UpdateFile if the file already exists create, _, err := client.Repositories.CreateFile(ctx, owner, repo, file, opts) if err != nil { return diag.FromErr(err) @@ -414,6 +410,14 @@ func resourceGithubRepositoryFileUpdate(ctx context.Context, d *schema.ResourceD return diag.FromErr(err) } + if d.HasChanges("repository", "file", "branch") { + newResourceID, err := buildID(repo, file, branch) + if err != nil { + return diag.FromErr(err) + } + d.SetId(newResourceID) + } + return resourceGithubRepositoryFileRead(ctx, d, meta) } @@ -472,23 +476,12 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD if err != nil { return nil, err } - if branch != "" { - opts.Ref = branch - if err := d.Set("branch", branch); err != nil { - return nil, err - } - } else { - - defaultBranch := repoInfo.GetDefaultBranch() - branch = defaultBranch - if err := d.Set("branch", branch); err != nil { - return nil, err - } - } - if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { - return nil, err + if branch == "" { + branch = repoInfo.GetDefaultBranch() } + opts.Ref = branch + fc, _, _, err := client.Repositories.GetContents(ctx, owner, repo, filePath, opts) if err != nil { return nil, err @@ -512,6 +505,13 @@ func resourceGithubRepositoryFileImport(ctx context.Context, d *schema.ResourceD "id": newResourceID, }) d.SetId(newResourceID) + + if err := d.Set("branch", branch); err != nil { + return nil, err + } + if err := d.Set("repository_id", int(repoInfo.GetID())); err != nil { + return nil, err + } if err = d.Set("overwrite_on_create", false); err != nil { return nil, err } From 0d8ebfee4a98d8b4ace93aa753205d4b13cfbe20 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 11 Feb 2026 05:52:01 +0200 Subject: [PATCH 15/19] fixup! Remove usage of autocreate_branch in `Read`, `Update` and `Delete` Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 35 +++-------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index ec3dcefd45..cbca1dbfad 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -277,15 +277,6 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat opts := &github.RepositoryContentGetOptions{} - if err := checkRepositoryBranchExists(ctx, client, owner, repoName, branch); err != nil { - if d.Get("autocreate_branch").(bool) { - branch = d.Get("autocreate_branch_source_branch").(string) - } else { - tflog.Info(ctx, "Removing repository path from state because the branch no longer exists in GitHub") - d.SetId("") - return nil - } - } opts.Ref = branch fc, _, _, err := client.Repositories.GetContents(ctx, owner, repoName, file, opts) @@ -294,6 +285,7 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat if errors.As(err, &errorResponse) && errorResponse.Response.StatusCode == http.StatusTooManyRequests { return diag.FromErr(err) } + return diag.FromErr(deleteResourceOn404AndSwallow304OtherwiseReturnError(err, d, "repository file %s/%s:%s:%s", owner, repoName, file, branch)) } if fc == nil { tflog.Info(ctx, "Removing repository path from state because it no longer exists in GitHub") @@ -378,21 +370,12 @@ func resourceGithubRepositoryFileUpdate(ctx context.Context, d *schema.ResourceD repo := d.Get("repository").(string) file := d.Get("file").(string) + branch := d.Get("branch").(string) + ctx = tflog.SetField(ctx, "repository", repo) ctx = tflog.SetField(ctx, "file", file) ctx = tflog.SetField(ctx, "owner", owner) - - branch := d.Get("branch").(string) - - if err := checkRepositoryBranchExists(ctx, client, owner, repo, branch); err != nil { - if d.Get("autocreate_branch").(bool) { - if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { - return diag.FromErr(err) - } - } else { - return diag.FromErr(err) - } - } + ctx = tflog.SetField(ctx, "branch", branch) opts := resourceGithubRepositoryFileOptions(d) @@ -435,16 +418,6 @@ func resourceGithubRepositoryFileDelete(ctx context.Context, d *schema.ResourceD } branch := d.Get("branch").(string) - - if err := checkRepositoryBranchExists(ctx, client, owner, repo, branch); err != nil { - if d.Get("autocreate_branch").(bool) { - if err := resourceGithubRepositoryFileCreateBranch(ctx, d, meta); err != nil { - return diag.FromErr(err) - } - } else { - return diag.FromErr(err) - } - } opts.Branch = github.Ptr(branch) _, _, err := client.Repositories.DeleteFile(ctx, owner, repo, file, opts) From d2f19df759f67792f02956f1d5fe5f1ee2ced37d Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 11 Feb 2026 05:53:46 +0200 Subject: [PATCH 16/19] Mark `autocreate_branch` as deprecated Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index cbca1dbfad..591750ad6d 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -111,6 +111,7 @@ func resourceGithubRepositoryFile() *schema.Resource { Description: "Automatically create the branch if it could not be found. Subsequent reads if the branch is deleted will occur from 'autocreate_branch_source_branch'", Default: false, DiffSuppressFunc: autoBranchDiffSuppressFunc, + Deprecated: "Use `github_branch` resource instead", }, "autocreate_branch_source_branch": { Type: schema.TypeString, @@ -119,6 +120,7 @@ func resourceGithubRepositoryFile() *schema.Resource { Description: "The branch name to start from, if 'autocreate_branch' is set. Defaults to 'main'.", RequiredWith: []string{"autocreate_branch"}, DiffSuppressFunc: autoBranchDiffSuppressFunc, + Deprecated: "Use `github_branch` resource instead", }, "autocreate_branch_source_sha": { Type: schema.TypeString, @@ -127,6 +129,7 @@ func resourceGithubRepositoryFile() *schema.Resource { Description: "The commit hash to start from, if 'autocreate_branch' is set. Defaults to the tip of 'autocreate_branch_source_branch'. If provided, 'autocreate_branch_source_branch' is ignored.", RequiredWith: []string{"autocreate_branch"}, DiffSuppressFunc: autoBranchDiffSuppressFunc, + Deprecated: "Use `github_branch` resource instead", }, }, CustomizeDiff: diffRepository, From aa0a114c8b9d313aa4227d373c88da6c980bea93 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 11 Feb 2026 15:48:53 +0200 Subject: [PATCH 17/19] fixup! Address review comments Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 591750ad6d..4af806f533 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -2,7 +2,6 @@ package github import ( "context" - "errors" "fmt" "net/http" "net/url" @@ -199,11 +198,12 @@ func resourceGithubRepositoryFileCreate(ctx context.Context, d *schema.ResourceD return diag.FromErr(err) } } - checkOpt.Ref = branch } else { branch = repoInfo.GetDefaultBranch() } + checkOpt.Ref = branch + opts := resourceGithubRepositoryFileOptions(d) if opts.Message == nil { @@ -284,10 +284,6 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat fc, _, _, err := client.Repositories.GetContents(ctx, owner, repoName, file, opts) if err != nil { - var errorResponse *github.ErrorResponse - if errors.As(err, &errorResponse) && errorResponse.Response.StatusCode == http.StatusTooManyRequests { - return diag.FromErr(err) - } return diag.FromErr(deleteResourceOn404AndSwallow304OtherwiseReturnError(err, d, "repository file %s/%s:%s:%s", owner, repoName, file, branch)) } if fc == nil { From 1fe800a3a23bdb34a58c6f05d799223321ec206a Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 11 Feb 2026 16:23:04 +0200 Subject: [PATCH 18/19] fixup! Change to use `UpdateFile` in `Update` Signed-off-by: Timo Sand --- github/resource_github_repository_file.go | 5 ++- .../resource_github_repository_file_test.go | 31 +++++-------------- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/github/resource_github_repository_file.go b/github/resource_github_repository_file.go index 4af806f533..3a31edb55e 100644 --- a/github/resource_github_repository_file.go +++ b/github/resource_github_repository_file.go @@ -382,13 +382,12 @@ func resourceGithubRepositoryFileUpdate(ctx context.Context, d *schema.ResourceD opts.Message = github.Ptr(fmt.Sprintf("Update %s", file)) } - // TODO: Use UpdateFile if the file already exists - create, _, err := client.Repositories.CreateFile(ctx, owner, repo, file, opts) + update, _, err := client.Repositories.UpdateFile(ctx, owner, repo, file, opts) if err != nil { return diag.FromErr(err) } - if err = d.Set("commit_sha", create.GetSHA()); err != nil { + if err = d.Set("commit_sha", update.GetSHA()); err != nil { return diag.FromErr(err) } diff --git a/github/resource_github_repository_file_test.go b/github/resource_github_repository_file_test.go index 7520403be8..8dba39abba 100644 --- a/github/resource_github_repository_file_test.go +++ b/github/resource_github_repository_file_test.go @@ -33,30 +33,13 @@ func TestAccGithubRepositoryFile(t *testing.T) { } `, repoName) check := resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr( - "github_repository_file.test", "content", - "bar", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "sha", - "ba0e162e1c47469e3fe4b393a8bf8c569f302116", - ), - resource.TestCheckResourceAttr( - "github_repository_file.test", "ref", - "main", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_author", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_email", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_message", - ), - resource.TestCheckResourceAttrSet( - "github_repository_file.test", "commit_sha", - ), + resource.TestCheckResourceAttr("github_repository_file.test", "content", "bar"), + resource.TestCheckResourceAttr("github_repository_file.test", "sha", "ba0e162e1c47469e3fe4b393a8bf8c569f302116"), + resource.TestCheckResourceAttr("github_repository_file.test", "ref", "main"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_author"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_email"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_message"), + resource.TestCheckResourceAttrSet("github_repository_file.test", "commit_sha"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_branch"), resource.TestCheckNoResourceAttr("github_repository_file.test", "autocreate_branch_source_sha"), From e2cb7f4ad1e3b5280fd423b7ad1d1bf2382a8fd1 Mon Sep 17 00:00:00 2001 From: Timo Sand Date: Wed, 11 Feb 2026 19:46:07 +0200 Subject: [PATCH 19/19] fixup! Update docs with missing fields Signed-off-by: Timo Sand --- website/docs/r/repository_file.html.markdown | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/website/docs/r/repository_file.html.markdown b/website/docs/r/repository_file.html.markdown index c67eec0784..8bd65b16fb 100644 --- a/website/docs/r/repository_file.html.markdown +++ b/website/docs/r/repository_file.html.markdown @@ -80,11 +80,11 @@ The following arguments are supported: - `overwrite_on_create` - (Optional) Enable overwriting existing files. If set to `true` it will overwrite an existing file with the same name. If set to `false` it will fail if there is an existing file with the same name. -- `autocreate_branch` - (Optional) Automatically create the branch if it could not be found. Defaults to false. Subsequent reads if the branch is deleted will occur from 'autocreate_branch_source_branch'. +- `autocreate_branch` - (Optional) **Deprecated** Automatically create the branch if it could not be found. Defaults to false. Subsequent reads if the branch is deleted will occur from 'autocreate_branch_source_branch'. Use the `github_branch` resource instead. -- `autocreate_branch_source_branch` - (Optional) The branch name to start from, if 'autocreate_branch' is set. Defaults to 'main'. +- `autocreate_branch_source_branch` - (Optional) **Deprecated** The branch name to start from, if 'autocreate_branch' is set. Defaults to 'main'. Use the `github_branch` resource instead. -- `autocreate_branch_source_sha` - (Optional) The commit hash to start from, if 'autocreate_branch' is set. Defaults to the tip of 'autocreate_branch_source_branch'. If provided, 'autocreate_branch_source_branch' is ignored. +- `autocreate_branch_source_sha` - (Optional) **Deprecated** The commit hash to start from, if 'autocreate_branch' is set. Defaults to the tip of 'autocreate_branch_source_branch'. If provided, 'autocreate_branch_source_branch' is ignored. Use the `github_branch` resource instead. ## Attributes Reference @@ -92,6 +92,8 @@ The following additional attributes are exported: - `commit_sha` - The SHA of the commit that modified the file. +- `repository_id` - The ID of the repository. + - `sha` - The SHA blob of the file. - `ref` - The name of the commit/branch/tag.