Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions github/resource_github_repository_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package github

import (
"context"
"errors"
"fmt"
"net/http"
"net/url"
Expand Down Expand Up @@ -331,6 +332,19 @@ func resourceGithubRepositoryFileRead(ctx context.Context, d *schema.ResourceDat
commit, err = getFileCommit(ctx, client, owner, repoName, file, ref)
}
if err != nil {
// The commit recorded in state, or any commit still containing the file,
// may be unreachable because the repository, branch or history is gone.
// That is "the resource no longer exists", not a failure to read it.
if ghErr, ok := errors.AsType[*github.ErrorResponse](err); ok && ghErr.Response != nil && ghErr.Response.StatusCode == http.StatusNotFound {
tflog.Info(ctx, "Removing repository file from state because its commit no longer exists in GitHub")
d.SetId("")
Comment on lines +338 to +340
return nil
}
if errors.Is(err, errFileCommitNotFound) {
tflog.Info(ctx, "Removing repository file from state because no commit contains it")
d.SetId("")
return nil
}
return diag.FromErr(err)
}
tflog.Debug(ctx, "Found file in commit", map[string]any{
Expand Down
7 changes: 6 additions & 1 deletion github/util_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ func checkRepositoryBranchExists(ctx context.Context, client *github.Client, own
return nil
}

// errFileCommitNotFound reports that no commit reachable from the requested ref
// still contains the file, so callers can remove the resource from state rather
// than surfacing a hard error.
var errFileCommitNotFound = errors.New("no commit contains the file")

func getFileCommit(ctx context.Context, client *github.Client, owner, repo, file, branch string) (*github.RepositoryCommit, error) {
opts := &github.CommitsListOptions{
SHA: branch,
Expand Down Expand Up @@ -89,7 +94,7 @@ func getFileCommit(ctx context.Context, client *github.Client, owner, repo, file
}
}

return nil, fmt.Errorf("cannot find file %s in repo %s/%s", file, owner, repo)
return nil, fmt.Errorf("cannot find file %s in repo %s/%s: %w", file, owner, repo, errFileCommitNotFound)
}

// getAutolinkByKeyPrefix returns a single autolink reference by key prefix that was configured for the given repository.
Expand Down
34 changes: 34 additions & 0 deletions github/util_repo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package github

import (
"context"
"errors"
"net/http"
"net/http/httptest"
"testing"
)

// Test_getFileCommit_NoCommitContainsFile locks in the errFileCommitNotFound
// sentinel. resourceGithubRepositoryFileRead relies on it to remove the resource
// from state instead of returning a hard error, so unwrapping this error would
// silently reintroduce that failure.
func Test_getFileCommit_NoCommitContainsFile(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
if _, err := w.Write([]byte("[]")); err != nil {
t.Errorf("failed to write response: %s", err)
}
}))
defer ts.Close()

client := mustCreateTestGitHubClient(t, ts.URL+"/")

_, err := getFileCommit(context.Background(), client, "owner", "repo", "some/file.txt", "main")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please use t.Context() instead

if err == nil {
t.Fatal("expected an error when no commit contains the file, got nil")
Comment on lines +26 to +28
}

if !errors.Is(err, errFileCommitNotFound) {
t.Errorf("errors.Is(err, errFileCommitNotFound) = false, want true; got error: %s", err)
}
}
Loading