fix(deps): update rust crate serde to v1.0.209 - abandoned #41
11 changed files with 1743 additions and 0 deletions
3
images/gitea/.dockerignore
Normal file
3
images/gitea/.dockerignore
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.git/
|
||||||
|
target/
|
||||||
|
README.adoc
|
1441
images/gitea/Cargo.lock
generated
Normal file
1441
images/gitea/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
22
images/gitea/Cargo.toml
Normal file
22
images/gitea/Cargo.toml
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
[package]
|
||||||
|
name = "gitea"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.2.0", features = ["cargo", "color", "unicode", "std", "derive"] }
|
||||||
|
color-eyre = "0.6.2"
|
||||||
|
reqwest = { version = "0.11.16", default-features = false, features = ["blocking", "json", "rustls-tls-native-roots"] }
|
||||||
|
serde_json = "1.0.95"
|
||||||
|
serde = { version = "1.0.159", features = ["derive"] }
|
||||||
|
time = { version = "0.3.20", features = ["formatting", "macros", "serde"] }
|
||||||
|
tracing = "0.1.37"
|
||||||
|
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
|
||||||
|
url = { version = "2.3.1", features = ["serde"] }
|
||||||
|
tracing-error = "0.2.0"
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = "debuginfo"
|
||||||
|
lto = true
|
41
images/gitea/Dockerfile
Normal file
41
images/gitea/Dockerfile
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
FROM rust:alpine AS builder
|
||||||
|
|
||||||
|
# Use a dummy project to ensure the crate index is up to date.
|
||||||
|
RUN set -e; \
|
||||||
|
cargo new --color always /tmp/dummy; \
|
||||||
|
cargo add --color always --manifest-path /tmp/dummy/Cargo.toml serde; \
|
||||||
|
rm -rf /tmp/dummy; \
|
||||||
|
cargo new --color always --bin /app
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
# openssl-dev \
|
||||||
|
# pkgconfig \
|
||||||
|
musl-dev
|
||||||
|
|
||||||
|
# Build dependencies with a dummy project to cache those regardless of changes
|
||||||
|
# in the actual source code
|
||||||
|
COPY ./Cargo.toml ./Cargo.lock /app/
|
||||||
|
RUN cargo build --color always --release --locked
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN touch -a -m ./src/main.rs && cargo build --color always --release --locked
|
||||||
|
|
||||||
|
FROM alpine AS pr
|
||||||
|
# FROM debian:bullseye-slim AS pr
|
||||||
|
|
||||||
|
RUN apk add --no-cache ca-certificates
|
||||||
|
# RUN set -e; \
|
||||||
|
# apt-get update; \
|
||||||
|
# apt-get install -y --no-install-recommends \
|
||||||
|
# ca-certificates; \
|
||||||
|
# rm -fr /var/apt/lists/*;
|
||||||
|
|
||||||
|
LABEL version="0.1.0"
|
||||||
|
|
||||||
|
ENV RUST_BACKTRACE=1
|
||||||
|
ENV RUST_LOG=info
|
||||||
|
|
||||||
|
COPY ./shims/pr/* /opt/resource/
|
||||||
|
COPY --from=builder /app/target/release/gitea /bin/
|
23
images/gitea/README.adoc
Normal file
23
images/gitea/README.adoc
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
= Gitea Concourse Resource
|
||||||
|
|
||||||
|
== Actions
|
||||||
|
|
||||||
|
[source,yaml]
|
||||||
|
----
|
||||||
|
- name: prs
|
||||||
|
type: gitea-pr
|
||||||
|
icon: git
|
||||||
|
source:
|
||||||
|
access_token: ((my_cred.token))
|
||||||
|
repo: some-repo
|
||||||
|
owner: some_user_or_org
|
||||||
|
hostname: https://example.com
|
||||||
|
----
|
||||||
|
|
||||||
|
=== `check`
|
||||||
|
|
||||||
|
Returns the list of currently active pull requests
|
||||||
|
|
||||||
|
=== `in`
|
||||||
|
|
||||||
|
Writes information about the currently active pull requests to `$1/prs.json`, which can be consumed by a `load_var` step.
|
2
images/gitea/shims/pr/check
Executable file
2
images/gitea/shims/pr/check
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
/bin/gitea pr check "$@"
|
2
images/gitea/shims/pr/in
Executable file
2
images/gitea/shims/pr/in
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
/bin/gitea pr in "$@"
|
2
images/gitea/shims/pr/out
Executable file
2
images/gitea/shims/pr/out
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
/bin/gitea pr out "$@"
|
147
images/gitea/src/cmd/pr.rs
Normal file
147
images/gitea/src/cmd/pr.rs
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
use std::fs;
|
||||||
|
use std::io::{self, Read};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use color_eyre::eyre::{self, Context};
|
||||||
|
use color_eyre::Result;
|
||||||
|
use reqwest::blocking::{Client, Response};
|
||||||
|
use reqwest::header::HeaderMap;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use crate::types::PullRequest;
|
||||||
|
use crate::Action;
|
||||||
|
|
||||||
|
static USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION"));
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
struct Source {
|
||||||
|
access_token: String,
|
||||||
|
owner: String,
|
||||||
|
repo: String,
|
||||||
|
url: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
struct Version {
|
||||||
|
prs: Vec<String>,
|
||||||
|
#[serde(with = "time::serde::timestamp")]
|
||||||
|
timestamp: OffsetDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
struct Config {
|
||||||
|
/// Resource configuration.
|
||||||
|
/// Passed verbatim from the definition in the pipeline.
|
||||||
|
source: Source,
|
||||||
|
/// For 'check':
|
||||||
|
/// Previous version of this resource.
|
||||||
|
/// Will be empty for the very first request.
|
||||||
|
/// For 'in':
|
||||||
|
/// The version metadata to create this as.
|
||||||
|
version: Option<Version>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn make_client(src: &Source) -> Result<Client> {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(
|
||||||
|
"Authorization",
|
||||||
|
format!("token {}", src.access_token).try_into()?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Client::builder()
|
||||||
|
.default_headers(headers)
|
||||||
|
.user_agent(USER_AGENT)
|
||||||
|
.build()
|
||||||
|
.map_err(From::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn fetch(src: &Source) -> Result<Response> {
|
||||||
|
let client = make_client(&src).wrap_err("Failed to create HTTP client")?;
|
||||||
|
let url = src
|
||||||
|
.url
|
||||||
|
.join(&format!("api/v1/repos/{}/{}/pulls", src.owner, src.repo))
|
||||||
|
.wrap_err("Invalid URL")?;
|
||||||
|
|
||||||
|
client
|
||||||
|
.get(url)
|
||||||
|
.query(&[("sort", "oldest"), ("state", "open")])
|
||||||
|
.send()
|
||||||
|
.map_err(From::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn action_check(conf: Config) -> Result<()> {
|
||||||
|
let prs: Vec<PullRequest> = fetch(&conf.source)?.json()?;
|
||||||
|
let mut version = Version {
|
||||||
|
prs: prs.iter().map(|pr| pr.number.to_string()).collect(),
|
||||||
|
timestamp: OffsetDateTime::now_utc(),
|
||||||
|
};
|
||||||
|
version.prs.sort_unstable();
|
||||||
|
|
||||||
|
let out = if let Some(prev) = conf.version {
|
||||||
|
if prev.prs == version.prs {
|
||||||
|
vec![prev]
|
||||||
|
} else {
|
||||||
|
vec![prev, version]
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vec![version]
|
||||||
|
};
|
||||||
|
|
||||||
|
serde_json::to_writer_pretty(io::stdout(), &out)
|
||||||
|
.wrap_err("Failed to write result to stdout")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
fn action_in(conf: Config, dest: impl AsRef<Path>) -> Result<()> {
|
||||||
|
let version = if let Some(version) = conf.version {
|
||||||
|
version
|
||||||
|
} else {
|
||||||
|
eyre::bail!("Version missing in 'in' action.");
|
||||||
|
};
|
||||||
|
|
||||||
|
let bytes = fetch(&conf.source)?.bytes()?;
|
||||||
|
let prs: Vec<PullRequest> = serde_json::from_slice(&bytes)?;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut prs: Vec<_> = prs.iter().map(|pr| pr.number.to_string()).collect();
|
||||||
|
prs.sort_unstable();
|
||||||
|
if version.prs != prs {
|
||||||
|
eyre::bail!("Version to fetch does not match current resource.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = dest.as_ref().join("prs.json");
|
||||||
|
let _ = fs::create_dir_all(dest);
|
||||||
|
fs::write(&path, &bytes)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(skip_all)]
|
||||||
|
pub(crate) fn run(action: &Action) -> Result<()> {
|
||||||
|
let config: Config = {
|
||||||
|
let mut buf = String::new();
|
||||||
|
io::stdin()
|
||||||
|
.read_to_string(&mut buf)
|
||||||
|
.wrap_err("Failed to read from stdin")?;
|
||||||
|
|
||||||
|
if buf.is_empty() {
|
||||||
|
eyre::bail!("No data received on stdin");
|
||||||
|
}
|
||||||
|
|
||||||
|
serde_json::from_str(&buf).wrap_err("Failed to parse stdin")?
|
||||||
|
};
|
||||||
|
|
||||||
|
match action {
|
||||||
|
Action::Check => action_check(config),
|
||||||
|
Action::In { dest } => action_in(config, dest),
|
||||||
|
Action::Out => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
54
images/gitea/src/main.rs
Normal file
54
images/gitea/src/main.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
use color_eyre::Result;
|
||||||
|
use tracing_error::ErrorLayer;
|
||||||
|
use tracing_subscriber::fmt;
|
||||||
|
use tracing_subscriber::prelude::*;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
#[command(propagate_version = true)]
|
||||||
|
struct Cli {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Subcommand)]
|
||||||
|
enum Commands {
|
||||||
|
Pr {
|
||||||
|
#[command(subcommand)]
|
||||||
|
action: Action,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Subcommand)]
|
||||||
|
pub(crate) enum Action {
|
||||||
|
Check,
|
||||||
|
In { dest: PathBuf },
|
||||||
|
Out,
|
||||||
|
}
|
||||||
|
|
||||||
|
mod types;
|
||||||
|
mod cmd {
|
||||||
|
pub mod pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[tracing::instrument]
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
let filter_layer = EnvFilter::try_from_default_env()
|
||||||
|
.or_else(|_| EnvFilter::try_new("info"))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
tracing_subscriber::registry()
|
||||||
|
.with(filter_layer)
|
||||||
|
.with(ErrorLayer::new(fmt::format::Pretty::default()))
|
||||||
|
.init();
|
||||||
|
|
||||||
|
let cli = Cli::parse();
|
||||||
|
|
||||||
|
match &cli.command {
|
||||||
|
Commands::Pr { action } => cmd::pr::run(action),
|
||||||
|
}
|
||||||
|
}
|
6
images/gitea/src/types.rs
Normal file
6
images/gitea/src/types.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
pub struct PullRequest {
|
||||||
|
pub number: u64,
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue