Skip to content

Commit e1416fe

Browse files
committed
resource/gitlab_repository_file: Support auto base64 encoding for content
Closes: #956
1 parent 6002c55 commit e1416fe

File tree

5 files changed

+136
-38
lines changed

5 files changed

+136
-38
lines changed

docs/data-sources/repository_file.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ data "gitlab_repository_file" "example" {
4040

4141
- `blob_id` (String) The blob id.
4242
- `commit_id` (String) The commit id.
43-
- `content` (String) base64 encoded file content. No other encoding is currently supported, because of a [GitLab API bug](https://gitlab.com/gitlab-org/gitlab/-/issues/342430).
43+
- `content` (String) File content. If the content is not yet base64 encoded, it will be encoded automatically. No other encoding is currently supported, because of a [GitLab API bug](https://gitlab.com/gitlab-org/gitlab/-/issues/342430).
4444
- `content_sha256` (String) File content sha256 digest.
4545
- `encoding` (String) The file content encoding.
4646
- `file_name` (String) The filename.

docs/resources/repository_file.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ resource "gitlab_repository_file" "this" {
5656

5757
- `branch` (String) Name of the branch to which to commit to.
5858
- `commit_message` (String) Commit message.
59-
- `content` (String) base64 encoded file content. No other encoding is currently supported, because of a [GitLab API bug](https://gitlab.com/gitlab-org/gitlab/-/issues/342430).
59+
- `content` (String) File content. If the content is not yet base64 encoded, it will be encoded automatically. No other encoding is currently supported, because of a [GitLab API bug](https://gitlab.com/gitlab-org/gitlab/-/issues/342430).
6060
- `file_path` (String) The full path of the file. It must be relative to the root of the project without a leading slash `/`.
6161
- `project` (String) The name or ID of the project.
6262

internal/provider/resource_gitlab_repository_file.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,20 @@ func resourceGitlabRepositoryFileCreate(ctx context.Context, d *schema.ResourceD
107107
log.Printf("[DEBUG] gitlab_repository_file: got lock to create %s/%s", project, filePath)
108108

109109
client := meta.(*gitlab.Client)
110+
// NOTE: for backwards-compatibility reasons, we also support an already given base64 encoding,
111+
// otherwise we encode the `content` to base64.
112+
content := d.Get("content").(string)
113+
if _, err := base64.StdEncoding.DecodeString(content); err != nil {
114+
log.Printf("[DEBUG] gitlab_repository_file: given content '%s' is not a valid base64 encoded string, encoding it ...", content)
115+
content = base64.StdEncoding.EncodeToString([]byte(content))
116+
}
110117

111118
options := &gitlab.CreateFileOptions{
112119
Branch: gitlab.String(d.Get("branch").(string)),
113120
Encoding: gitlab.String(encoding),
114121
AuthorEmail: gitlab.String(d.Get("author_email").(string)),
115122
AuthorName: gitlab.String(d.Get("author_name").(string)),
116-
Content: gitlab.String(d.Get("content").(string)),
123+
Content: gitlab.String(content),
117124
CommitMessage: gitlab.String(d.Get("commit_message").(string)),
118125
}
119126
if startBranch, ok := d.GetOk("start_branch"); ok {
@@ -189,12 +196,20 @@ func resourceGitlabRepositoryFileUpdate(ctx context.Context, d *schema.ResourceD
189196
Ref: gitlab.String(branch),
190197
}
191198

199+
// NOTE: for backwards-compatibility reasons, we also support an already given base64 encoding,
200+
// otherwise we encode the `content` to base64.
201+
content := d.Get("content").(string)
202+
if _, err := base64.StdEncoding.DecodeString(content); err != nil {
203+
log.Printf("[DEBUG] gitlab_repository_file: given content '%s' is not a valid base64 encoded string, encoding it ...", content)
204+
content = base64.StdEncoding.EncodeToString([]byte(content))
205+
}
206+
192207
updateOptions := &gitlab.UpdateFileOptions{
193208
Branch: gitlab.String(branch),
194209
Encoding: gitlab.String(encoding),
195210
AuthorEmail: gitlab.String(d.Get("author_email").(string)),
196211
AuthorName: gitlab.String(d.Get("author_name").(string)),
197-
Content: gitlab.String(d.Get("content").(string)),
212+
Content: gitlab.String(content),
198213
CommitMessage: gitlab.String(d.Get("commit_message").(string)),
199214
}
200215
if startBranch, ok := d.GetOk("start_branch"); ok {
@@ -276,14 +291,6 @@ func resourceGitlabRepositoryFileDelete(ctx context.Context, d *schema.ResourceD
276291
return nil
277292
}
278293

279-
func validateBase64Content(v interface{}, k string) (we []string, errors []error) {
280-
content := v.(string)
281-
if _, err := base64.StdEncoding.DecodeString(content); err != nil {
282-
errors = append(errors, fmt.Errorf("given repository file content '%s' is not base64 encoded, but must be", content))
283-
}
284-
return
285-
}
286-
287294
func resourceGitLabRepositoryFileParseId(id string) (string, string, string, error) {
288295
parts := strings.SplitN(id, ":", 3)
289296
if len(parts) != 3 {

internal/provider/resource_gitlab_repository_file_test.go

Lines changed: 106 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,30 +114,32 @@ func TestAccGitlabRepositoryFile_concurrentResources(t *testing.T) {
114114
})
115115
}
116116

117-
func TestAccGitlabRepositoryFile_validationOfBase64Content(t *testing.T) {
118-
cases := []struct {
119-
givenContent string
120-
expectedIsValidContent bool
121-
}{
122-
{
123-
givenContent: "not valid base64",
124-
expectedIsValidContent: false,
125-
},
126-
{
127-
givenContent: "bWVvdyBtZW93IG1lb3c=",
128-
expectedIsValidContent: true,
129-
},
130-
}
117+
func TestAccGitlabRepositoryFile_createOnNewBranch(t *testing.T) {
118+
testAccCheck(t)
131119

132-
for _, c := range cases {
133-
_, errs := validateBase64Content(c.givenContent, "dummy")
134-
if len(errs) > 0 == c.expectedIsValidContent {
135-
t.Fatalf("content '%s' was either expected to be valid base64 but isn't or to be invalid base64 but actually is", c.givenContent)
136-
}
137-
}
120+
var file gitlab.File
121+
testProject := testAccCreateProject(t)
122+
123+
resource.Test(t, resource.TestCase{
124+
PreCheck: func() { testAccPreCheck(t) },
125+
ProviderFactories: providerFactories,
126+
CheckDestroy: testAccCheckGitlabRepositoryFileDestroy,
127+
Steps: []resource.TestStep{
128+
{
129+
Config: testAccGitlabRepositoryFileStartBranchConfig(testProject.ID),
130+
Check: resource.ComposeTestCheckFunc(
131+
testAccCheckGitlabRepositoryFileExists("gitlab_repository_file.this", &file),
132+
testAccCheckGitlabRepositoryFileAttributes(&file, &testAccGitlabRepositoryFileAttributes{
133+
FilePath: "meow.txt",
134+
Content: "bWVvdyBtZW93IG1lb3c=",
135+
}),
136+
),
137+
},
138+
},
139+
})
138140
}
139141

140-
func TestAccGitlabRepositoryFile_createOnNewBranch(t *testing.T) {
142+
func TestAccGitlabRepositoryFile_base64EncodingWithTextContent(t *testing.T) {
141143
testAccCheck(t)
142144

143145
var file gitlab.File
@@ -149,7 +151,74 @@ func TestAccGitlabRepositoryFile_createOnNewBranch(t *testing.T) {
149151
CheckDestroy: testAccCheckGitlabRepositoryFileDestroy,
150152
Steps: []resource.TestStep{
151153
{
152-
Config: testAccGitlabRepositoryFileStartBranchConfig(testProject.ID),
154+
Config: fmt.Sprintf(`
155+
resource "gitlab_repository_file" "this" {
156+
project = %d
157+
file_path = "meow.txt"
158+
branch = "main"
159+
content = "Hello World, meow"
160+
author_email = "[email protected]"
161+
author_name = "Meow Meowington"
162+
commit_message = "feature: add launch codes"
163+
}
164+
`, testProject.ID),
165+
Check: resource.ComposeTestCheckFunc(
166+
testAccCheckGitlabRepositoryFileExists("gitlab_repository_file.this", &file),
167+
testAccCheckGitlabRepositoryFileAttributes(&file, &testAccGitlabRepositoryFileAttributes{
168+
FilePath: "meow.txt",
169+
Content: "SGVsbG8gV29ybGQsIG1lb3c=",
170+
}),
171+
),
172+
},
173+
// Update content
174+
{
175+
Config: fmt.Sprintf(`
176+
resource "gitlab_repository_file" "this" {
177+
project = %d
178+
file_path = "meow.txt"
179+
branch = "main"
180+
content = "Hello World, meow UPDATED"
181+
author_email = "[email protected]"
182+
author_name = "Meow Meowington"
183+
commit_message = "feature: add launch codes"
184+
}
185+
`, testProject.ID),
186+
Check: resource.ComposeTestCheckFunc(
187+
testAccCheckGitlabRepositoryFileExists("gitlab_repository_file.this", &file),
188+
testAccCheckGitlabRepositoryFileAttributes(&file, &testAccGitlabRepositoryFileAttributes{
189+
FilePath: "meow.txt",
190+
Content: "SGVsbG8gV29ybGQsIG1lb3cgVVBEQVRFRA==",
191+
}),
192+
),
193+
},
194+
// Update to already base64 encoded content, but same content, yields in an empty plan
195+
{
196+
Config: fmt.Sprintf(`
197+
resource "gitlab_repository_file" "this" {
198+
project = %d
199+
file_path = "meow.txt"
200+
branch = "main"
201+
content = "SGVsbG8gV29ybGQsIG1lb3cgVVBEQVRFRA=="
202+
author_email = "[email protected]"
203+
author_name = "Meow Meowington"
204+
commit_message = "feature: add launch codes"
205+
}
206+
`, testProject.ID),
207+
PlanOnly: true,
208+
},
209+
// Update content and already base64 encode it
210+
{
211+
Config: fmt.Sprintf(`
212+
resource "gitlab_repository_file" "this" {
213+
project = %d
214+
file_path = "meow.txt"
215+
branch = "main"
216+
content = "bWVvdyBtZW93IG1lb3c="
217+
author_email = "[email protected]"
218+
author_name = "Meow Meowington"
219+
commit_message = "feature: add launch codes"
220+
}
221+
`, testProject.ID),
153222
Check: resource.ComposeTestCheckFunc(
154223
testAccCheckGitlabRepositoryFileExists("gitlab_repository_file.this", &file),
155224
testAccCheckGitlabRepositoryFileAttributes(&file, &testAccGitlabRepositoryFileAttributes{
@@ -158,6 +227,21 @@ func TestAccGitlabRepositoryFile_createOnNewBranch(t *testing.T) {
158227
}),
159228
),
160229
},
230+
// Update to not-yet base64 encoded content, but same content, yields in an empty plan
231+
{
232+
Config: fmt.Sprintf(`
233+
resource "gitlab_repository_file" "this" {
234+
project = %d
235+
file_path = "meow.txt"
236+
branch = "main"
237+
content = "meow meow meow"
238+
author_email = "[email protected]"
239+
author_name = "Meow Meowington"
240+
commit_message = "feature: add launch codes"
241+
}
242+
`, testProject.ID),
243+
PlanOnly: true,
244+
},
161245
},
162246
})
163247
}

internal/provider/schema_gitlab_repository_file.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package provider
22

33
import (
4+
"encoding/base64"
5+
46
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
57
"github.com/xanzy/go-gitlab"
68
)
@@ -40,10 +42,15 @@ func gitlabRepositoryFileGetSchema() map[string]*schema.Schema {
4042
Computed: true,
4143
},
4244
"content": {
43-
Description: "base64 encoded file content. No other encoding is currently supported, because of a [GitLab API bug](https://gitlab.com/gitlab-org/gitlab/-/issues/342430).",
44-
Type: schema.TypeString,
45-
Required: true,
46-
ValidateFunc: validateBase64Content,
45+
Description: "File content. If the content is not yet base64 encoded, it will be encoded automatically. No other encoding is currently supported, because of a [GitLab API bug](https://gitlab.com/gitlab-org/gitlab/-/issues/342430).",
46+
Type: schema.TypeString,
47+
Required: true,
48+
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
49+
if _, err := base64.StdEncoding.DecodeString(new); err != nil {
50+
new = base64.StdEncoding.EncodeToString([]byte(new))
51+
}
52+
return old == new
53+
},
4754
},
4855
"content_sha256": {
4956
Description: "File content sha256 digest.",

0 commit comments

Comments
 (0)