難しいことではありませんが、それほど明白ではありません。
読み取り/更新しようとしていたファイルは 2.4 Mb で、このファイルを (SevenZip を使用して) 512K まで圧縮できたので、レポで読み取り/更新できるようになりましたが、1Mb を超えるファイルを読み取り/更新したかったのです。
これを実現するには、GitHub の GraphQL API を使用する必要がありました。読み取り/更新に関心のある特定のファイルの SHA1 を取得するために必要でした。
Git API や GraphQL を使ったことがないので、GraphQL クライアント (GraphQL.Client と GraphQL.Client.Serializer.Newtonsoft) を利用することにしました。
GraphQL を使用すると、GitHub リポジトリにある既存のファイル/ブロブの SHA-1 ID を取得できました。BLOB の SHA-1 を取得したら、GIT Data API を介して問題のファイルを簡単に取得できました。
その後、コンテンツを変更し、変更を Octokit.Net 経由で GitHub にプッシュすることができました。
これは決して洗練されたものではありませんが、これをやろうとしている他の人のために何かでこれを締めくくりたいと思いました.
次のスタックオーバー フロー スレッドの功績によるものです。
public async Task<string> GetSha1(string owner, string personalToken, string repositoryName, string pathName, string branch = "master")
{
string basicValue = Convert.ToBase64String(Encoding.UTF8.GetBytes($"{owner}:{personalToken}"));
var graphQLClient = new GraphQLHttpClient("https://api.github.com/graphql", new NewtonsoftJsonSerializer());
graphQLClient.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", basicValue);
var getShaRequest = new GraphQLRequest
{
Query = @"
query {
repository(owner: """+owner+@""", name: """+ repositoryName +@""") {
object(expression: """ + branch + @":" + pathName +@""") {
... on Blob {
oid
}
}
}
}",
Variables = new
{
}
};
var graphQLResponse = await graphQLClient.SendQueryAsync<ResponseType>(getShaRequest, cancellationToken: CancellationToken.None);
return graphQLResponse.Data.Repository.Object.Oid;
}
ここに私のヘルパークラスがあります
public class ContentResponseType
{
public string content { get; set; }
public string encoding { get; set; }
public string url { get; set; }
public string sha { get; set; }
public long size { get; set; }
}
public class DataObject
{
public string Oid;
}
public class Repository
{
public DataObject Object;
}
public class ResponseType
{
public Repository Repository { get; set; }
}
上記の方法で提供された SHA-1 を使用してコンテンツを取得するファイルを次に示します。
public async Task<ContentResponseType> RetrieveFileAsync(string owner, string personalToken, string repositoryName, string pathName, string branch = "master")
{
var sha1 = await this.GetSha1(owner: owner, personalToken: personalToken, repositoryName: repositoryName, pathName: pathName, branch: branch);
var url = this.GetBlobUrl(owner, repositoryName, sha1);
var req = this.BuildRequestMessage(url, personalToken);
using (var httpClient = new HttpClient())
{
var resp = await httpClient.SendAsync(req);
if (resp.StatusCode != System.Net.HttpStatusCode.OK)
{
throw new Exception($"error happens when downloading the {req.RequestUri}, statusCode={resp.StatusCode}");
}
using (var ms = new MemoryStream())
{
await resp.Content.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
StreamReader reader = new StreamReader(ms);
var jsonString = reader.ReadToEnd();
return System.Text.Json.JsonSerializer.Deserialize<ContentResponseType>(jsonString);
}
}
}
これが私のコンソールテストアプリです...
static async Task Main(string[] args)
{
// GitHub variables
var owner = "{Put Owner Name here}";
var personalGitHubToken = "{Put your Token here}";
var repo = "{Put Repo Name Here}";
var branch = "master";
var referencePath = "{Put path and filename here}";
// Get the existing Domain Model file
var api = new GitHubRepoApi();
var response = await api.RetrieveFileAsync(owner:owner, personalToken: personalGitHubToken, repositoryName: repo, pathName: referencePath, branch:branch);
var currentFileText = Encoding.UTF8.GetString(Convert.FromBase64String(response.content));
// Change the description of the JSON Domain Model
currentFileText = currentFileText.Replace(@"""description"":""SubDomain", @"""description"":""Domain");
// Update the changes back to GitHub repo using Octokit
var client = new GitHubClient(new Octokit.ProductHeaderValue(repo));
var tokenAuth = new Credentials(personalGitHubToken);
client.Credentials = tokenAuth;
// Read back the changes to confirm all works
var updateChangeSet = await client.Repository.Content.UpdateFile(owner, repo, referencePath,
new UpdateFileRequest("Domain Model was updated via automation", currentFileText, response.sha, branch));
response = await api.RetrieveFileAsync(owner: owner, personalToken: personalGitHubToken, repositoryName: repo, pathName: referencePath, branch: branch);
currentFileText = Encoding.UTF8.GetString(Convert.FromBase64String(response.content));
}
これを達成するには他にも多くの方法があると確信していますが、これが私にとってうまくいった方法であり、これが他の誰かの生活を少し楽にするのに役立つことを願っています.
乾杯ジョン