Skip to content

Commit e90dc61

Browse files
committed
feat: Add update functionality to rename existing GitHub branches and update documentation
1 parent 38e68ad commit e90dc61

File tree

2 files changed

+84
-1
lines changed

2 files changed

+84
-1
lines changed

github/resource_github_branch.go

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ func resourceGithubBranch() *schema.Resource {
1515
return &schema.Resource{
1616
Create: resourceGithubBranchCreate,
1717
Read: resourceGithubBranchRead,
18+
Update: resourceGithubBranchUpdate,
1819
Delete: resourceGithubBranchDelete,
1920
Importer: &schema.ResourceImporter{
2021
State: resourceGithubBranchImport,
@@ -30,7 +31,6 @@ func resourceGithubBranch() *schema.Resource {
3031
"branch": {
3132
Type: schema.TypeString,
3233
Required: true,
33-
ForceNew: true,
3434
Description: "The repository branch to create.",
3535
},
3636
"source_branch": {
@@ -184,6 +184,29 @@ func resourceGithubBranchDelete(d *schema.ResourceData, meta interface{}) error
184184
return nil
185185
}
186186

187+
func resourceGithubBranchUpdate(d *schema.ResourceData, meta interface{}) error {
188+
if !d.HasChange("branch") {
189+
return resourceGithubBranchRead(d, meta)
190+
}
191+
192+
ctx := context.WithValue(context.Background(), ctxId, d.Id())
193+
client := meta.(*Owner).v3client
194+
orgName := meta.(*Owner).name
195+
repoName, oldBranchName, err := parseTwoPartID(d.Id(), "repository", "branch")
196+
if err != nil {
197+
return err
198+
}
199+
newBranchName := d.Get("branch").(string)
200+
201+
if _, _, err := client.Repositories.RenameBranch(ctx, orgName, repoName, oldBranchName, newBranchName); err != nil {
202+
return fmt.Errorf("error renaming GitHub branch %s/%s (%s -> %s): %w", orgName, repoName, oldBranchName, newBranchName, err)
203+
}
204+
205+
d.SetId(buildTwoPartID(repoName, newBranchName))
206+
207+
return resourceGithubBranchRead(d, meta)
208+
}
209+
187210
func resourceGithubBranchImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
188211
repoName, branchName, err := parseTwoPartID(d.Id(), "repository", "branch")
189212
if err != nil {

github/resource_github_branch_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,4 +209,64 @@ func TestAccGithubBranch(t *testing.T) {
209209

210210
})
211211

212+
t.Run("renames a branch without replacement", func(t *testing.T) {
213+
214+
initialConfig := fmt.Sprintf(`
215+
resource "github_repository" "test" {
216+
name = "tf-acc-test-%[1]s"
217+
auto_init = true
218+
}
219+
220+
resource "github_branch" "test" {
221+
repository = github_repository.test.id
222+
branch = "initial"
223+
}
224+
`, randomID)
225+
226+
renamedConfig := fmt.Sprintf(`
227+
resource "github_repository" "test" {
228+
name = "tf-acc-test-%[1]s"
229+
auto_init = true
230+
}
231+
232+
resource "github_branch" "test" {
233+
repository = github_repository.test.id
234+
branch = "renamed"
235+
}
236+
`, randomID)
237+
238+
testCase := func(t *testing.T, mode string) {
239+
resource.Test(t, resource.TestCase{
240+
PreCheck: func() { skipUnlessMode(t, mode) },
241+
Providers: testAccProviders,
242+
Steps: []resource.TestStep{
243+
{
244+
Config: initialConfig,
245+
},
246+
{
247+
Config: renamedConfig,
248+
Check: resource.ComposeTestCheckFunc(
249+
resource.TestCheckResourceAttr(
250+
"github_branch.test", "branch", "renamed",
251+
),
252+
),
253+
},
254+
},
255+
})
256+
}
257+
258+
t.Run("with an anonymous account", func(t *testing.T) {
259+
t.Skip("anonymous account not supported for this operation")
260+
})
261+
262+
t.Run("with an individual account", func(t *testing.T) {
263+
testCase(t, individual)
264+
})
265+
266+
t.Run("with an organization account", func(t *testing.T) {
267+
testCase(t, organization)
268+
})
269+
270+
})
271+
212272
}

0 commit comments

Comments
 (0)