Compare commits

..

2 commits

5 changed files with 34 additions and 14 deletions

View file

@ -3,6 +3,13 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## [v0.4.3](https://codeberg.org/ThetaDev/artifactview/compare/v0.4.2..v0.4.3) - 2024-06-22
### 🐛 Bug Fixes
- 404 error on GitHub comment creation - ([d8c3ab4](https://codeberg.org/ThetaDev/artifactview/commit/d8c3ab4f36727f118b31683db87d287d9945ee14))
## [v0.4.2](https://codeberg.org/ThetaDev/artifactview/compare/v0.4.1..v0.4.2) - 2024-06-22 ## [v0.4.2](https://codeberg.org/ThetaDev/artifactview/compare/v0.4.1..v0.4.2) - 2024-06-22
### 🐛 Bug Fixes ### 🐛 Bug Fixes

2
Cargo.lock generated
View file

@ -141,7 +141,7 @@ dependencies = [
[[package]] [[package]]
name = "artifactview" name = "artifactview"
version = "0.4.2" version = "0.4.3"
dependencies = [ dependencies = [
"async_zip", "async_zip",
"axum", "axum",

View file

@ -1,6 +1,6 @@
[package] [package]
name = "artifactview" name = "artifactview"
version = "0.4.2" version = "0.4.3"
edition = "2021" edition = "2021"
authors = ["ThetaDev <thetadev@magenta.de>"] authors = ["ThetaDev <thetadev@magenta.de>"]
license = "MIT" license = "MIT"

View file

@ -76,13 +76,19 @@ artifacts.
![Pull request comment](./resources/screenshotPrComment.png) ![Pull request comment](./resources/screenshotPrComment.png)
To accomplish that, simply add this step to your CI workflow (after uploading the To accomplish that, simply add this step to your CI workflow (after uploading the
artifacts). artifacts). Note that the workflow URL has to be built differently on GitHub and
Forgejo, so this solution is sadly not cross-forge compatible.
```yaml ```yaml
- name: 🔗 Artifactview PR comment - name: 🔗 Artifactview PR comment (Forgejo)
if: ${{ always() && github.event_name == 'pull_request' }} if: ${{ always() && github.event_name == 'pull_request' }}
run: | run: |
curl -SsL --fail-with-body -w "\n" -X POST https://av.thetadev.de/.well-known/api/prComment -H "Content-Type: application/json" --data "{\"url\": \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_NUMBER\", \"pr\": ${{ github.event.number }}}" curl -SsL --fail-with-body -w "\n" -X POST https://av.thetadev.de/.well-known/api/prComment -H "Content-Type: application/json" --data "{\"url\": \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_NUMBER\", \"pr\": ${{ github.event.number }}}"
- name: 🔗 Artifactview PR comment (GitHub)
if: ${{ always() && github.event_name == 'pull_request' }}
run: |
curl -SsL --fail-with-body -w "\n" -X POST https://av.thetadev.de/.well-known/api/prComment -H "Content-Type: application/json" --data "{\"url\": \"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID\", \"pr\": ${{ github.event.number }}}"
``` ```
## API ## API
@ -254,11 +260,12 @@ Example list: `foo;bar`, example map: `foo=>f1;bar=>b1`
### Access tokens ### Access tokens
GitHub does not allow downloading artifacts for public repositories for unauthenticated GitHub does not allow downloading artifacts for public repositories for unauthenticated
users. So you need to setup an access token to use Artifactview with GitHub. These are users. So you need to setup an access token to use Artifactview with GitHub.
the permissions that need to be enabled:
- Repository access: All repositories If you are not using the `prComment` feature, you can use a fine-grained access token
- Repository permissions: Pull requests (Read and write) with the "Public repositories (read-only)" permission. If you want to create pull
request comments, you have to use a classic token with the "public_repo" scope enabled
(the fine-grained tokens did not work in my test).
Forgejo does not require access tokens to download artifacts on public repositories, so Forgejo does not require access tokens to download artifacts on public repositories, so
you only need to create a token if you want to use the `prComment`-API. In this case, you only need to create a token if you want to use the `prComment`-API. In this case,

View file

@ -269,6 +269,7 @@ impl ArtifactApi {
} }
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn list(&self, query: &RunQuery, cached: bool) -> Result<Vec<Artifact>> { pub async fn list(&self, query: &RunQuery, cached: bool) -> Result<Vec<Artifact>> {
let cache_key = query.cache_key(); let cache_key = query.cache_key();
let fut = async { let fut = async {
@ -290,6 +291,7 @@ impl ArtifactApi {
} }
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn fetch(&self, query: &ArtifactQuery) -> Result<Artifact> { pub async fn fetch(&self, query: &ArtifactQuery) -> Result<Artifact> {
if query.is_github() { if query.is_github() {
self.fetch_github(query).await self.fetch_github(query).await
@ -305,6 +307,7 @@ impl ArtifactApi {
} }
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn download(&self, artifact: &Artifact, path: &Path) -> Result<()> { pub async fn download(&self, artifact: &Artifact, path: &Path) -> Result<()> {
if artifact.expired { if artifact.expired {
return Err(Error::Expired); return Err(Error::Expired);
@ -416,10 +419,9 @@ impl ArtifactApi {
if let Err(e) = resp.error_for_status_ref() { if let Err(e) = resp.error_for_status_ref() {
let status = resp.status(); let status = resp.status();
let msg = resp.json::<ApiError>().await.ok(); let msg = resp.json::<ApiError>().await.ok();
Err(Error::HttpClient( let msg_str = msg.map(|msg| msg.message).unwrap_or(e.to_string()).into();
msg.map(|msg| msg.message).unwrap_or(e.to_string()).into(), tracing::error!("API error: {msg_str}");
status, Err(Error::HttpClient(msg_str, status))
))
} else { } else {
Ok(resp) Ok(resp)
} }
@ -492,6 +494,7 @@ impl ArtifactApi {
.header(header::AUTHORIZATION, format!("token {token}"))) .header(header::AUTHORIZATION, format!("token {token}")))
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn workflow_run(&self, query: &RunQuery) -> Result<WorkflowRun> { pub async fn workflow_run(&self, query: &RunQuery) -> Result<WorkflowRun> {
if query.is_github() { if query.is_github() {
self.workflow_run_github(query).await self.workflow_run_github(query).await
@ -554,6 +557,7 @@ impl ArtifactApi {
Ok(run.into()) Ok(run.into())
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn add_comment( pub async fn add_comment(
&self, &self,
query: QueryRef<'_>, query: QueryRef<'_>,
@ -621,8 +625,8 @@ impl ArtifactApi {
) -> Result<u64> { ) -> Result<u64> {
if let Some(old_comment_id) = old_comment_id { if let Some(old_comment_id) = old_comment_id {
let url = format!( let url = format!(
"https://api.github.com/repos/{}/{}/issues/{}/comments/{}", "https://api.github.com/repos/{}/{}/issues/comments/{}",
query.user, query.repo, issue_id, old_comment_id query.user, query.repo, old_comment_id
); );
if recreate { if recreate {
Self::send_api_req_empty(self.req_github(Method::DELETE, url)?).await?; Self::send_api_req_empty(self.req_github(Method::DELETE, url)?).await?;
@ -650,6 +654,7 @@ impl ArtifactApi {
Ok(new_c.id) Ok(new_c.id)
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn find_comment( pub async fn find_comment(
&self, &self,
query: QueryRef<'_>, query: QueryRef<'_>,
@ -702,6 +707,7 @@ impl ArtifactApi {
Ok(None) Ok(None)
} }
#[tracing::instrument(level = "error", skip_all)]
pub async fn get_pr(&self, query: QueryRef<'_>, pr_id: u64) -> Result<PullRequest> { pub async fn get_pr(&self, query: QueryRef<'_>, pr_id: u64) -> Result<PullRequest> {
let req = if query.is_github() { let req = if query.is_github() {
self.get_github(format!( self.get_github(format!(