cli: Add `--tag` option to `rad issue open`
Also include a simple script for importing GitHub issues.
This commit is contained in:
parent
8667553740
commit
9fd3527196
|
|
@ -27,7 +27,7 @@ Usage
|
||||||
rad issue [<option>...]
|
rad issue [<option>...]
|
||||||
rad issue delete <issue-id> [<option>...]
|
rad issue delete <issue-id> [<option>...]
|
||||||
rad issue list [--assigned <did>] [<option>...]
|
rad issue list [--assigned <did>] [<option>...]
|
||||||
rad issue open [--title <title>] [--description <text>] [<option>...]
|
rad issue open [--title <title>] [--description <text>] [--tag <tag>] [<option>...]
|
||||||
rad issue react <issue-id> [--emoji <char>] [<option>...]
|
rad issue react <issue-id> [--emoji <char>] [<option>...]
|
||||||
rad issue show <issue-id> [<option>...]
|
rad issue show <issue-id> [<option>...]
|
||||||
rad issue state <issue-id> [--closed | --open | --solved] [<option>...]
|
rad issue state <issue-id> [--closed | --open | --solved] [<option>...]
|
||||||
|
|
@ -42,7 +42,7 @@ Options
|
||||||
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
#[derive(serde::Deserialize, serde::Serialize, Debug)]
|
||||||
pub struct Metadata {
|
pub struct Metadata {
|
||||||
title: String,
|
title: String,
|
||||||
labels: Vec<Tag>,
|
tags: Vec<Tag>,
|
||||||
assignees: Vec<Did>,
|
assignees: Vec<Did>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,6 +70,7 @@ pub enum Operation {
|
||||||
Open {
|
Open {
|
||||||
title: Option<String>,
|
title: Option<String>,
|
||||||
description: Option<String>,
|
description: Option<String>,
|
||||||
|
tags: Vec<Tag>,
|
||||||
},
|
},
|
||||||
Show {
|
Show {
|
||||||
id: Rev,
|
id: Rev,
|
||||||
|
|
@ -108,6 +109,7 @@ impl Args for Options {
|
||||||
let mut reaction: Option<Reaction> = None;
|
let mut reaction: Option<Reaction> = None;
|
||||||
let mut description: Option<String> = None;
|
let mut description: Option<String> = None;
|
||||||
let mut state: Option<State> = None;
|
let mut state: Option<State> = None;
|
||||||
|
let mut tags = Vec::new();
|
||||||
let mut announce = true;
|
let mut announce = true;
|
||||||
|
|
||||||
while let Some(arg) = parser.next()? {
|
while let Some(arg) = parser.next()? {
|
||||||
|
|
@ -118,6 +120,13 @@ impl Args for Options {
|
||||||
Long("title") if op == Some(OperationName::Open) => {
|
Long("title") if op == Some(OperationName::Open) => {
|
||||||
title = Some(parser.value()?.to_string_lossy().into());
|
title = Some(parser.value()?.to_string_lossy().into());
|
||||||
}
|
}
|
||||||
|
Long("tag") if op == Some(OperationName::Open) => {
|
||||||
|
let val = parser.value()?;
|
||||||
|
let name = term::args::string(&val);
|
||||||
|
let tag = Tag::new(name)?;
|
||||||
|
|
||||||
|
tags.push(tag);
|
||||||
|
}
|
||||||
Long("closed") if op == Some(OperationName::State) => {
|
Long("closed") if op == Some(OperationName::State) => {
|
||||||
state = Some(State::Closed {
|
state = Some(State::Closed {
|
||||||
reason: CloseReason::Other,
|
reason: CloseReason::Other,
|
||||||
|
|
@ -172,7 +181,11 @@ impl Args for Options {
|
||||||
}
|
}
|
||||||
|
|
||||||
let op = match op.unwrap_or_default() {
|
let op = match op.unwrap_or_default() {
|
||||||
OperationName::Open => Operation::Open { title, description },
|
OperationName::Open => Operation::Open {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
tags,
|
||||||
|
},
|
||||||
OperationName::Show => Operation::Show {
|
OperationName::Show => Operation::Show {
|
||||||
id: id.ok_or_else(|| anyhow!("an issue must be provided"))?,
|
id: id.ok_or_else(|| anyhow!("an issue must be provided"))?,
|
||||||
},
|
},
|
||||||
|
|
@ -215,8 +228,9 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
Operation::Open {
|
Operation::Open {
|
||||||
title: Some(title),
|
title: Some(title),
|
||||||
description: Some(description),
|
description: Some(description),
|
||||||
|
tags,
|
||||||
} => {
|
} => {
|
||||||
let issue = issues.create(title, description, &[], &[], &signer)?;
|
let issue = issues.create(title, description, tags.as_slice(), &[], &signer)?;
|
||||||
show_issue(&issue)?;
|
show_issue(&issue)?;
|
||||||
}
|
}
|
||||||
Operation::Show { id } => {
|
Operation::Show { id } => {
|
||||||
|
|
@ -238,10 +252,14 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
issue.react(*comment_id, reaction, &signer)?;
|
issue.react(*comment_id, reaction, &signer)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Operation::Open { title, description } => {
|
Operation::Open {
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
tags,
|
||||||
|
} => {
|
||||||
let meta = Metadata {
|
let meta = Metadata {
|
||||||
title: title.unwrap_or("Enter a title".to_owned()),
|
title: title.unwrap_or("Enter a title".to_owned()),
|
||||||
labels: vec![],
|
tags,
|
||||||
assignees: vec![],
|
assignees: vec![],
|
||||||
};
|
};
|
||||||
let yaml = serde_yaml::to_string(&meta)?;
|
let yaml = serde_yaml::to_string(&meta)?;
|
||||||
|
|
@ -278,7 +296,7 @@ pub fn run(options: Options, ctx: impl term::Context) -> anyhow::Result<()> {
|
||||||
let issue = issues.create(
|
let issue = issues.create(
|
||||||
&meta.title,
|
&meta.title,
|
||||||
description.trim(),
|
description.trim(),
|
||||||
meta.labels.as_slice(),
|
meta.tags.as_slice(),
|
||||||
meta.assignees
|
meta.assignees
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(cob::ActorId::from)
|
.map(cob::ActorId::from)
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,8 @@ pub enum TagError {
|
||||||
pub struct Tag(String);
|
pub struct Tag(String);
|
||||||
|
|
||||||
impl Tag {
|
impl Tag {
|
||||||
pub fn new(name: impl Into<String>) -> Result<Self, TagError> {
|
pub fn new(name: impl ToString) -> Result<Self, TagError> {
|
||||||
let name = name.into();
|
let name = name.to_string();
|
||||||
|
|
||||||
if name.chars().any(|c| c.is_whitespace()) || name.is_empty() {
|
if name.chars().any(|c| c.is_whitespace()) || name.is_empty() {
|
||||||
return Err(TagError::InvalidName(name));
|
return Err(TagError::InvalidName(name));
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Import a GitHub issue into Radicle.
|
||||||
|
#
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if ! command -v curl > /dev/null; then
|
||||||
|
echo "Error: curl is not installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v jq > /dev/null; then
|
||||||
|
echo "Error: jq is not installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v rad > /dev/null; then
|
||||||
|
echo "Error: rad is not installed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the correct number of arguments is provided
|
||||||
|
if [ "$#" -ne 3 ]; then
|
||||||
|
echo "Usage: $0 <org> <repo> <issue>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
owner="$1"
|
||||||
|
repo="$2"
|
||||||
|
issue="$3"
|
||||||
|
|
||||||
|
url="https://api.github.com/repos/${owner}/${repo}/issues/${issue}"
|
||||||
|
|
||||||
|
# Fetch the issue data using the GitHub API
|
||||||
|
response="$(curl -s "$url")"
|
||||||
|
|
||||||
|
# Extract the title and body from the JSON response
|
||||||
|
title="$(echo "$response" | jq -r '.title')"
|
||||||
|
body="$(echo "$response" | jq -r '.body')"
|
||||||
|
labels="$(echo "$response" | jq -r '.labels | .[].name')"
|
||||||
|
|
||||||
|
tags=()
|
||||||
|
for label in $labels; do
|
||||||
|
tags+=("--tag" "$label")
|
||||||
|
done
|
||||||
|
|
||||||
|
rad issue open --title "$title" "${tags[@]}" --description "$body" --no-announce
|
||||||
Loading…
Reference in New Issue