logo elektroda
logo elektroda
X
logo elektroda

How to programmatically access Github pull requests, commits and download artifacts?

p.kaczmarek2 2205 23

TL;DR

  • A C# utility accesses GitHub pull requests, commits, workflow runs, and build artifacts to automate firmware downloads for OpenBeken and similar WiFi MCU projects.
  • It uses Octokit for repository data, HttpClient for GitHub API calls, and JsonSerializer to parse workflows and artifacts into C# classes.
  • The example queries commit d763b28c9a433217f3c95ef4c9bbd6777a32486d and workflow run 12305496423 via GitHub API endpoints.
  • After iterating artifact links, the utility downloads ZIP build files to disk for later OTA processing.
  • Unauthenticated requests can hit GitHub's API rate limit, while authenticated tokens get a higher limit.
Generated by the language model.
ADVERTISEMENT
📢 Listen (AI):
  • List of completed checks in GitHub Actions
    GitHub Actions workflows can be used to automatically build and test firmware on each commit. They may or may not create Github Releases, if not, build files are downloadable only via Github Action details. By default, those binaries require manual download, but here I will show you how to automate it.

    The goal of the project is to create an auto-updater for WiFi MCU firmware, like for BK7231, W800/W600, or anything else supported by OpenBeken.

    The basic presentation of Github Actions Binaries used in
    OpenBeken was shown here, today I am going to create small C# utility to automate that. Let's start.

    Used tools
    For this presentation, I will use following tools:
    - Visual Studio as a C# IDE and compiler
    - Octokit library from NuGet for easier Github API access
    - in some later parts, I will also use HTTPClient to directly access Github API, as I had some issues with Octokit. Responses will be parsed via JSONSerializer

    Octokit library
    First you'll need the Octokit library. Octokit provides easy access to Github API and can be downloaded within Visual Studio via "Manage NuGet Packages":
    NuGet Package Manager screen in Visual Studio with the Octokit library installed.
    Add it to your stock Console program and make sure you have correct usings:
    Code: C#
    Log in, to see the code


    Initializing GitHubClient
    Octokit library is using asynchronous tasks to run, so if your main function is not a task, you'll need to await for the result. Here's basic GitHubClient initialization:
    Code: C#
    Log in, to see the code



    Github Access Token
    This is not required for listing pull requests, but needed for artifacts. You will also obviously need it for the write access. Login to Github and go to Settings:
    Screenshot of the user menu on the GitHub page.
    then to Developer settings:
    Screenshot of GitHub settings menu.
    and then to Tokens. I have used "Classic" mode:
    Screenshot of GitHub personal access token settings
    Create a token, make sure to write it down. Choose the token scopes depending on what you are going to use to the token for. Don't give full write access to token if you don't want to use it to write to repository and use separate token for reach purpose you have.
    Finally, add the authentication code to your sample:
    Code: C#
    Log in, to see the code



    Enumerating pull requests
    Now it's time to get this list:
    https://github.com/openshwprojects/OpenBK7231T_App/pulls
    This can be done with PullRequest object:
    Code: C#
    Log in, to see the code

    Result:
    List of pull requests in console


    Enumerating commit
    Once you have Pull Request, you can get the latest commit. All commits can be listed in similiar way:
    Code: C#
    Log in, to see the code

    Result:
    Screenshot of a console application showing a list of GitHub pull requests.



    Accessing workflows
    For workflows, you'll need a separate function that will get JSON information from Github.
    The URL we want to access is the following:
    https://api.github.com/repos/openshwprojects/OpenBK7231T_App/commits/d763b28c9a433217f3c95ef4c9bbd6777a32486d/check-runs
    The commit Hash to be inserted there.
    Returned JSON is very simple:
    Code: JSON
    Log in, to see the code

    It's basically a JSON representation of each build here:
    GitHub pull request list with highlighted test results.
    We're very close!
    So, let's prepare the HttpClient and do GET request.
    Code: C#
    Log in, to see the code

    Then, let's put resulting JSON data into the classes with JsonSerializer:
    Code: C#
    Log in, to see the code


    Iterating the runs
    Once you have a list of workflows, you can iterate it:
    Code: C / C++
    Log in, to see the code

    Result:
    Screenshot of build results and statuses in a program console.


    Fetching artifacts
    Now we need to get links to zip files. We will need to extract a numerical ID for that. The ID can be found in workflow run data:
    Code: C#
    Log in, to see the code

    Here is a sample run ID: 12328623947
    You can now construct link like:
    https://api.github.com/repos/openshwprojects/OpenBK7231T_App/actions/runs/12305496423/artifacts
    Visiting this link yields following JSON:
    Code: JSON
    Log in, to see the code

    It's time to parse it. Here is function call:
    Code: C#
    Log in, to see the code

    And the implementation:
    Code: C#
    Log in, to see the code

    Again, the JSON data is deserialized into classes with JsonSerializer. Used classes:
    Code: C#
    Log in, to see the code

    Finally it's time to iterate them:
    Code: C#
    Log in, to see the code

    Result:
    Screenshot showing console output with a link to GitHub Actions artifacts.

    Downloading ZIP files
    Now we finally have ZIP file links, there's not much left to do:
    Code: C#
    Log in, to see the code

    Download handler:
    Code: C#
    Log in, to see the code

    Finally, after a few moments of downloading, we're getting OBK build files on our drive:
    Files of various types in the ConsoleApp8 application folder.
    Now it's time to futher process them, maybe send them to devices via OTA, but it's a task for another topic.


    Warning!
    Without authentication, you can easily hit API rate limit:
    
    Error: API rate limit exceeded for 123.234.233.121. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
    Press any key to exit...
    


    Summary
    This was the first part of Github Artifacts downloading presentation. In this part we've learned how to access Github API to list pull requests, commits, workflows and artifacts. We've also managed to download built files.
    In the next part I will present the tool that I based on the knowledge shown here:
    Screenshot of Form1 application showing interface for updating OpenBK7231T via GitHub
    This tool will be able to automatically keep OBK device updated to the latest build from given PR, thus making testing and development easier.
    Stay tuned!
    What would YOU have used Github API for?


    Full demo code is in the description:
    Attachments:
    • gitAPIdemo.zip (1.9 KB) You must be logged in to download this attachment.

    Cool? Ranking DIY
    Helpful post? Buy me a coffee.
    About Author
    p.kaczmarek2
    Moderator Smart Home
    Offline 
    p.kaczmarek2 wrote 14400 posts with rating 12329, helped 650 times. Been with us since 2014 year.
  • ADVERTISEMENT
  • #2 21350736
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    Repository with a very early and dirty draft of mentioned tool:
    https://github.com/openshwprojects/OBKotaTool
    My private TODO for upcoming days:
    - add field for Github key and store settings in JSON
    - instead of a combobox for chip type, send Tasmota STATUS packet and determine chip type that way
    - support multiple IP addresses in target box
    - maybe command line interface?
    Tool is currently tested with Beken and ESP32, works good
    @divadiow @max4elektroda @insmod @DeDaMrAz

    Hopefully it can make testing of PRs easier, especially if you setup like 3 devices and it will flash them in chain. Should be good as long as the PR does not break OTA.

    Added after 1 [hours] 27 [minutes]:

    Update: managed to call STATUS
    Screenshot of Visual Studio with the PROTATool project open and code highlighted.

    Added after 3 [minutes]:

    Screenshot of a program code snippet in an IDE with a highlighted if condition.

    Added after 5 [hours]:

    PROTA tool now has downloadable builds!
    Screenshot of the build process in GitHub Actions for OBKotaTool.
    Can anyone check if exe is downloadable and runs?
    https://github.com/openshwprojects/OBKotaTool
    Helpful post? Buy me a coffee.
  • #4 21351344
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    Now you need a Github API key, a PR link, and device IP.

    btw: Shall I do the same for https://github.com/openshwprojects/BK7231GUIFlashTool ?
    Helpful post? Buy me a coffee.
  • #6 21351397
    divadiow
    Level 38  
    Posts: 4845
    Help: 421
    Rate: 853
    cool
    Screenshot of OpenBK7231T software with configuration options and change log overview.
  • #7 21351401
    DeDaMrAz
    Level 22  
    Posts: 596
    Help: 34
    Rate: 125
    This will help new chip implementation and testing and speed up the process but a large margin!!

    Now I can't wait for my new modules to arrive :D
  • #8 21351410
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    I hope you guys realize that now, if you push a change to that pull request, the tool will automatically update your device. It queries Github PR in the background constantly, just to detect the change. That's the whole point of that tool.

    Now I'm adding support for multiple IPs:
    Screenshot of the OpenBK7231T application tool's GUI with fields for Github API key, IP addresses, and pull request link.
    https://github.com/openshwprojects/OBKotaTool

    It should choose the correct binary for each target device platform.
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT
  • #9 21351424
    DeDaMrAz
    Level 22  
    Posts: 596
    Help: 34
    Rate: 125
    Suggestion, as you already have a mechanism to determine what chip type is on that IP, a log window would be nice where that info would be displayed. Such is current build, platform (maybe option for future addons in there)?
  • #10 21351434
    divadiow
    Level 38  
    Posts: 4845
    Help: 421
    Rate: 853
    build, still running, already showing

    Screenshot of a software compilation application interface.
  • #11 21351438
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    I think I've handled this issue. If commit is available, but there are no artifacts yet, it shall retry every 5 seconds with a new message in log:
    Screenshot of Visual Studio showing a C# code snippet with an else statement highlighted in a red box.
    Helpful post? Buy me a coffee.
  • #12 21355899
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    Another idea.

    What if we implement this tool in the Web App or like in a Web Page? So it's done online? A web utility that can be run anywhere, and can either update OBKs to given release, or to given PR.

    @max4elektroda @divadiow @insmod @DeDaMrAz
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT
  • #13 21355911
    divadiow
    Level 38  
    Posts: 4845
    Help: 421
    Rate: 853
    that sounds excellent
  • #14 21355915
    insmod
    Level 31  
    Posts: 1353
    Help: 160
    Rate: 425
    >>21355899 If it's web (html/js), then count me out.
    But, maybe use .net8 and avalonia, then it will be cross-platform too. And it may work in browser with wasm.
  • #15 21355941
    max4elektroda
    Level 24  
    Posts: 745
    Help: 47
    Rate: 183
    p.kaczmarek2 wrote:
    What if we implement this tool in the Web App or like in a Web Page?

    My 2 cents: Web App - very good, Web Page - even better
  • #17 21357978
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    I will try to make web version someday, but first I will focus on finishing C# one.

    @insmod you're doing great things with porting so focus on that for now if you can. We can do testing much faster with the current PROTA tool, even if it runs on Windows.

    PS: This tool is already useful, we're testing ADS1115 with @DeDaMrAz and it helps a lot https://github.com/openshwprojects/OpenBK7231T_App/pull/1474
    Helpful post? Buy me a coffee.
  • ADVERTISEMENT
  • #19 21363838
    JimmyBob
    Level 2  
    Posts: 2
    It helped me, Thank you so much.
  • #22 21374912
    p.kaczmarek2
    Moderator Smart Home
    Posts: 14400
    Help: 650
    Rate: 12329
    So you want to also support that kind of links directly?
    Helpful post? Buy me a coffee.
  • #23 21374917
    divadiow
    Level 38  
    Posts: 4845
    Help: 421
    Rate: 853
    I mean, it'd be useful on the odd occasion . Just a nice-to-have.

    Added after 2 [minutes]:

    but yes, I appreciate it's for PRs :)
  • #24 21518979
    divadiow
    Level 38  
    Posts: 4845
    Help: 421
    Rate: 853
    how does this tab in EF fit in with the PROTA tool?

    Screenshot of BK7231 Easy UART Flasher tool for downloading and flashing firmware.

    I can't seem to get it to do anything
📢 Listen (AI):

Topic summary

✨ The discussion centers on programmatically accessing GitHub pull requests, commits, and downloading build artifacts to automate firmware updates for WiFi MCUs such as BK7231, W800, and W600 supported by OpenBeken. A C# utility named PROTA tool was developed using Visual Studio and the Octokit library to interact with the GitHub API, with fallback to HTTPClient for direct API calls. The tool automates detection of new commits in pull requests, downloads corresponding build binaries from GitHub Actions artifacts, and flashes multiple target devices over the network. Features include chip type detection via Tasmota STATUS packets, support for multiple IP addresses, and retry mechanisms for artifact availability. The tool is tested on Beken and ESP32 platforms and facilitates faster testing of pull requests by automatically updating devices when PR changes occur. Future plans include a web-based version for cross-platform use, possibly leveraging .NET 8 and Avalonia with WebAssembly. The tool currently focuses on pull request artifacts rather than GitHub Actions run artifacts or releases, though support for these was discussed as a potential enhancement. The PROTA tool repository and pull requests are publicly available for collaboration and further development.
Generated by the language model.

FAQ

TL;DR: In 3 API stages, "works like a charm," this C# workflow helps firmware developers list PRs, get the latest commit SHA, fetch GitHub Actions artifacts, and download ZIP builds for OTA testing. It also led to PROTA, which polls GitHub and can auto-update multiple devices from one PR. [#21357982]

Why it matters: This gives firmware testers a repeatable way to move from a pull request to a flashable build without manually opening GitHub Actions pages.

Approach Current thread status Best fit Limitation
Windows C# app Working and prioritized first Fastest path to a usable updater Windows-focused for now
Web app / web page Requested and viewed positively Run anywhere online Deferred until the C# version is finished
.NET 8 Avalonia with WASM Suggested by a participant Cross-platform, possible browser path Only a proposal in the thread

Key insight: The most important design choice is to treat the PR as the entry point, then resolve commit → check-runs → artifacts. If artifacts are not ready yet, retry instead of failing immediately. [#21351438]

Quick Facts

  • The sample commit check-runs response shows 18 check runs for one SHA, which is enough to map a single commit to multiple workflow outcomes. [#21348573]
  • The sample artifacts response shows 15 artifacts for one Actions run, each with an archive_download_url that points to a ZIP download. [#21348573]
  • PROTA was updated to retry every 5 seconds when a commit exists but artifacts are not published yet, reducing false failures during active CI builds. [#21351438]
  • The tool was reported as working with Beken and ESP32 targets, and later gained support for multiple IP addresses in one update flow. [#21350736]
  • A practical test setup mentioned using 3 devices in a chain so repeated PR flashes become easier during hardware bring-up and regression testing. [#21350736]

How do I programmatically list GitHub pull requests for openshwprojects/OpenBK7231T_App in C# using Octokit?

Use GitHubClient from Octokit, set owner = "openshwprojects" and repo = "OpenBK7231T_App", then call client.PullRequest.GetAllForRepository(owner, repo). Iterate the returned list and print pr.Number, pr.Title, pr.User.Login, and pr.State. The example wraps this inside RunAsync().GetAwaiter().GetResult() because Octokit uses async tasks. That gives you the same PR set shown on the repository Pull Requests page, but in C# code. [#21348573]

What is Octokit, and why would you use it instead of calling the GitHub API directly with HttpClient?

"Octokit" is a C# client library that accesses the GitHub API, its key characteristic is that it exposes GitHub objects such as pull requests and commits as typed async methods. Use it when you want fast PR and commit access with less boilerplate. The thread uses Octokit for listing pull requests and commits, but switches to HttpClient for workflows and artifacts because the author had issues with Octokit there. That mixed approach keeps simple tasks simple and still allows raw endpoint access when needed. [#21348573]

How can I get the latest commit SHA from a GitHub pull request before looking up workflow runs and artifacts?

Call client.PullRequest.Commits(owner, repo, pr.Number) and take the last item. The example uses var lastCommit = commits.LastOrDefault(); and then reads lastCommit.Sha. That SHA becomes the input for the next API call to /commits/{sha}/check-runs. If the PR has no commits, LastOrDefault() returns null, so check that before building workflow URLs. [#21348573]

What is a GitHub Actions artifact, and how is it different from a GitHub Release download?

"GitHub Actions artifact" is a build output package that a workflow stores for later download, its key characteristic is that it is tied to a specific workflow run rather than a formal repository release. In the thread, build files may exist only inside GitHub Actions details and may not appear as GitHub Releases. That is why the updater reads archive_download_url from the artifacts API and downloads ZIP files directly from the run. [#21348573]

How do I fetch GitHub check-runs or workflow information for a specific commit SHA from the GitHub API?

Send an authenticated GET request to /repos/{owner}/{repo}/commits/{sha}/check-runs with HttpClient. The example adds a Bearer token and a User-Agent header, then deserializes the JSON into CheckRunsResponse. In the sample response, one commit returned total_count: 18, and each check_run included name, status, html_url, and details_url. That data is enough to enumerate workflow activity for the commit. [#21348573]

Why do GitHub artifact requests need an access token even if listing pull requests can work without one?

Artifact access needs a token in this workflow because unauthenticated API use hits limits quickly, while authenticated requests get a higher limit. The thread explicitly says listing pull requests does not require a token, but artifacts do, and the sample code sets Credentials = new Credentials(GitHubToken) or sends a Bearer token with HttpClient. The token is also required if you want write access later, so the safer pattern is to create a scoped token and avoid broad permissions. [#21348573]

What causes the GitHub API rate limit exceeded error, and how do authenticated requests help when downloading artifacts?

The error happens when too many unauthenticated API requests come from one IP. The thread shows the exact failure text: API rate limit exceeded, followed by GitHub’s note that authenticated requests get a higher rate limit. Artifact download flows generate several calls per PR: pull request lookup, commit lookup, check-runs lookup, artifact lookup, and ZIP download. Adding a GitHub token raises the allowed request budget and makes repeated polling practical. [#21348573]

How can I extract the GitHub Actions run ID from a details_url like /actions/runs/... in C#?

Use a regular expression on details_url. The sample getSecondID() method matches runs/(\d+) and returns the first capture group. If details_url is https://github.com/.../actions/runs/12305496423/job/..., the method returns 12305496423. That run ID is then inserted into /actions/runs/{runId}/artifacts to fetch downloadable ZIP metadata. [#21348573]

What is the best way to deserialize GitHub check-runs and artifacts JSON into C# classes with System.Text.Json?

Create small DTO classes that match only the fields you need, then deserialize with JsonSerializer.Deserialize<T>(). The thread uses CheckRunsResponse with a [JsonPropertyName("check_runs")] property and a CheckRun class with fields like id, name, status, html_url, and details_url. For artifacts, it uses ArtifactResponse and Artifact with name and archive_download_url. This keeps the parser minimal even when the GitHub JSON is large. [#21348573]

How do I download artifact ZIP files from archive_download_url in C# and save them with the artifact name?

Use HttpClient, authenticate, stream the response, and write it to {artifactName}.zip. A simple 3-step flow works: 1. Read each artifact’s archive_download_url. 2. Call GetAsync(url) with the Bearer token and User-Agent. 3. Copy response.Content into a FileStream created with Path.Combine(Directory.GetCurrentDirectory(), $"{artifactName}.zip"). The example prints the saved path after each successful download. [#21348573]

Why would a tool like PROTA find a commit but no artifacts yet, and how should it retry until the build finishes?

A commit can appear before the GitHub Actions build has finished publishing artifacts. The thread describes exactly that edge case and says the tool should not stop there. Instead, it now retries every 5 seconds and adds a new log message until artifacts appear. That design matches real CI timing, where commit metadata is visible first and ZIP outputs arrive later. [#21351438]

How does PROTA detect the correct binary for each target device platform when flashing multiple IPs such as Beken and ESP32 devices?

It detects the chip type from the target device and uses that to choose the matching binary. The author’s TODO says the tool should send a Tasmota STATUS packet instead of relying on a chip-type combobox, and later reports, "managed to call STATUS." After that, support for multiple IPs was added, and the author says it should choose the correct binary for each target platform. The thread also states the tool was tested with Beken and ESP32. [#21351410]

PROTA currently expects a pull request URL, so how could support for direct GitHub Actions run links be added for bulk flashing or GA builds?

Support could be added by accepting /actions/runs/{id} URLs as a second input pattern and skipping the PR-to-commit step. The thread confirms the current tool is designed for PR links like /pull/<PR number>, but one participant asks whether direct Actions run links would be useful for bulk flashing and GA builds. That means the practical extension is URL pattern detection: PR URLs follow the existing path, while run URLs can go straight to artifacts lookup. [#21374917]

Web app vs Windows C# app vs .NET 8 Avalonia with WASM — which approach makes the most sense for a cross-platform OBKotaTool or PROTA updater?

The Windows C# app makes the most sense first, because it already works and the author chose to finish it before starting a web version. The thread shows strong interest in a web app or web page, while another participant suggested .NET 8 Avalonia with possible browser WASM support for cross-platform use. So the best roadmap in this discussion is: finish the current C# tool, then evaluate web delivery or Avalonia for portability. [#21357978]

How does the EF tab fit in with the PROTA tool, and why might it appear to do nothing?

The thread does not explain how the EF tab fits into PROTA, so its role remains unclear here. One participant asked on 2025-04-14 how that tab relates to the tool and said they could not get it to do anything, but no follow-up answer is included in the provided posts. If you are documenting the tool, treat the EF tab as unresolved until its purpose is described elsewhere. [#21518979]
Generated by the language model.
ADVERTISEMENT