chore: merge release-v0.3.1 into main

This commit is contained in:
Jack Wills
2023-06-04 00:40:40 +00:00
9 changed files with 281 additions and 367 deletions
+6 -16
View File
@@ -1,23 +1,13 @@
### 2023-03-30 ### 2023-06-04
### Chores ### Chores
+ dependencies updated, [7a9bdc9699594532e17a33e044ca0678693c8d3f], [58e03a750fe89b914b9069cb0c6c02a3d0929439], [b246e8c25af0c5136953afca7c694cda66550d9b] + github workflow ubuntu latest, build for x86 musl, [4fa841e6e74e3e10e3d3e82eac1a1ca1338814cf]
+ dependencies updated, [0caa92f6a4728d50d8b2d8f15d96a21112732ec5], [1fd1dfc75d6fa4e84451ebc845b9e1c730381f41]
### Docs + `Spans` -> `Line`, ratatui 0.21 update, [4679ddc885a9b35c901f3600b63fd9e86118264c], [0d37ac55018038363e5f92dc4215996f8cff7b2e]
+ README.md and screenshot updated, [73ab7580c61dd59c59f10872629111360afb9033] + `create_release.sh` updated, [7dec5f14a381d237c5e72fbf9551bcf398f93f3e]
### Features
+ Ability to delete a container, be warned, as this will force delete, closes #27, [937202fe34d1692693c62dd1a7ad19db37651233], [b25f8b18f4f2acd5c9af4a1d40655761d1bd720e]
+ Publish images to `ghcr.io` as well as Docker Hub, and correctly tag images with `latest` and the current sermver, [cb1271cf7f21c898020481ad85914a3dcc83ec93]
+ Replace `tui-rs` with [ratatui](https://github.com/tui-rs-revival/ratatui), [d431f850219b28af2bc45f3b6917377604596a40]
### Fixes ### Fixes
+ out of bound bug in `heading_bar()`, [b9c125da46fe0eb4aae15c354d87ac824e9cb83a] + workflow additional image fix, closes #29, [47cda44b8213cfb8c3807df6c43e3f5dc2452b57]
+ `-d` arg error text updated, [e0b49be84062abdfcb636418f57043fad37d06ec]
### Refactors
+ `popup()` use `saturating_x()` rather than `checked_x()`, [d628e8029942916053b3b7e72d363b1290fc5711]
+ button_item() include brackets, [7c92ffef7da20143a31706a310b5e6f2c3e0554f]
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
@@ -5,8 +5,7 @@ on:
- 'v[0-9]+.[0-9]+.[0-9]+' - 'v[0-9]+.[0-9]+.[0-9]+'
jobs: jobs:
deploy: deploy:
# Change this to latest - or ubuntu 20.04? runs-on: ubuntu-latest
runs-on: ubuntu-18.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -36,13 +35,12 @@ jobs:
- name: install cross - name: install cross
run: cargo install cross --git https://github.com/cross-rs/cross run: cargo install cross --git https://github.com/cross-rs/cross
# Build for linux x86_64 # Build for linux x86 musl
# Should this actually build for musl? - name: build x86_64-unknown-linux-musl
- name: build release linux_x86_64 run: cross build --target x86_64-unknown-linux-musl --release
run: cargo build --release
# Compress output into tar # Compress output into tar
- name: compress oxker_linux_x86_64 binary - name: compress aarch64 binary
run: tar -C target/release -czf ./oxker_linux_x86_64.tar.gz oxker run: tar -C target/x86_64-unknown-linux-musl/release -czf ./oxker_linux_x86_64.tar.gz oxker
# Build for linux aarch64, aka 64 bit pi 4 # Build for linux aarch64, aka 64 bit pi 4
- name: build aarch64-unknown-linux-musl - name: build aarch64-unknown-linux-musl
@@ -98,6 +96,7 @@ jobs:
-t ${{ secrets.DOCKERHUB_USERNAME }}/oxker:${{env.CURRENT_SEMVER}} \ -t ${{ secrets.DOCKERHUB_USERNAME }}/oxker:${{env.CURRENT_SEMVER}} \
-t ghcr.io/${{ github.repository_owner }}/oxker:latest \ -t ghcr.io/${{ github.repository_owner }}/oxker:latest \
-t ghcr.io/${{ github.repository_owner }}/oxker:${{env.CURRENT_SEMVER}} \ -t ghcr.io/${{ github.repository_owner }}/oxker:${{env.CURRENT_SEMVER}} \
--provenance=false --sbom=false \
--push \ --push \
-f containerised/Dockerfile . -f containerised/Dockerfile .
+12
View File
@@ -1,3 +1,15 @@
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.3.1'>v0.3.1</a>
### 2023-06-04
### Chores
+ github workflow ubuntu latest, build for x86 musl, [4fa841e6](https://github.com/mrjackwills/oxker/commit/4fa841e6e74e3e10e3d3e82eac1a1ca1338814cf)
+ dependencies updated, [0caa92f6](https://github.com/mrjackwills/oxker/commit/0caa92f6a4728d50d8b2d8f15d96a21112732ec5), [1fd1dfc7](https://github.com/mrjackwills/oxker/commit/1fd1dfc75d6fa4e84451ebc845b9e1c730381f41)
+ `Spans` -> `Line`, ratatui 0.21 update, [4679ddc8](https://github.com/mrjackwills/oxker/commit/4679ddc885a9b35c901f3600b63fd9e86118264c), [0d37ac55](https://github.com/mrjackwills/oxker/commit/0d37ac55018038363e5f92dc4215996f8cff7b2e)
+ `create_release.sh` updated, [7dec5f14](https://github.com/mrjackwills/oxker/commit/7dec5f14a381d237c5e72fbf9551bcf398f93f3e)
### Fixes
+ workflow additional image fix, closes [#29](https://github.com/mrjackwills/oxker/issues/29), [47cda44b](https://github.com/mrjackwills/oxker/commit/47cda44b8213cfb8c3807df6c43e3f5dc2452b57)
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.3.0'>v0.3.0</a> # <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.3.0'>v0.3.0</a>
### 2023-03-30 ### 2023-03-30
Generated
+185 -282
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,6 +1,6 @@
[package] [package]
name = "oxker" name = "oxker"
version = "0.3.0" version = "0.3.1"
edition = "2021" edition = "2021"
authors = ["Jack Wills <email@mrjackwills.com>"] authors = ["Jack Wills <email@mrjackwills.com>"]
description = "A simple tui to view & control docker containers" description = "A simple tui to view & control docker containers"
@@ -15,14 +15,14 @@ categories = ["command-line-utilities"]
anyhow = "1.0" anyhow = "1.0"
bollard = "0.14" bollard = "0.14"
cansi = "2.2" cansi = "2.2"
clap={version="4.2", features = ["derive", "unicode", "color"] } clap={version="4.3", features = ["derive", "unicode", "color"] }
crossterm = "0.26" crossterm = "0.26"
futures-util = "0.3" futures-util = "0.3"
parking_lot = {version= "0.12"} parking_lot = {version= "0.12"}
tokio = {version = "1.27", features=["full"]} tokio = {version = "1.28", features=["full"]}
tracing = "0.1" tracing = "0.1"
tracing-subscriber = "0.3" tracing-subscriber = "0.3"
ratatui = "0.20" ratatui = "0.21"
uuid = {version = "1.3", features = ["v4", "fast-rng"]} uuid = {version = "1.3", features = ["v4", "fast-rng"]}
[dev-dependencies] [dev-dependencies]
+13 -2
View File
@@ -176,26 +176,37 @@ cargo_test () {
# This will download GB's of docker images # This will download GB's of docker images
cargo_build () { cargo_build () {
cargo install cross cargo install cross
echo -e "${YELLOW}cargo build --release${RESET}" cargo_clean
cargo build --release echo -e "${YELLOW}cross build --target x86_64-unknown-linux-musl --release${RESET}"
cross build --target x86_64-unknown-linux-musl --release
ask_continue ask_continue
cargo_clean
echo -e "${YELLOW}cross build --target aarch64-unknown-linux-musl --release${RESET}" echo -e "${YELLOW}cross build --target aarch64-unknown-linux-musl --release${RESET}"
cross build --target aarch64-unknown-linux-musl --release cross build --target aarch64-unknown-linux-musl --release
ask_continue ask_continue
cargo_clean
echo -e "${YELLOW}cross build --target arm-unknown-linux-musleabihf --release${RESET}" echo -e "${YELLOW}cross build --target arm-unknown-linux-musleabihf --release${RESET}"
cross build --target arm-unknown-linux-musleabihf --release cross build --target arm-unknown-linux-musleabihf --release
ask_continue ask_continue
cargo_clean
echo -e "${YELLOW}cross build --target x86_64-pc-windows-gnu --release${RESET}" echo -e "${YELLOW}cross build --target x86_64-pc-windows-gnu --release${RESET}"
cross build --target x86_64-pc-windows-gnu --release cross build --target x86_64-pc-windows-gnu --release
ask_continue ask_continue
cargo_clean
} }
# $1 text to colourise # $1 text to colourise
release_continue () { release_continue () {
echo -e "\n${PURPLE}$1${RESET}" echo -e "\n${PURPLE}$1${RESET}"
ask_continue ask_continue
} }
# Clean/remove builds, due to issue with cross-rs
cargo_clean() {
echo -e "${YELLOW}cargo clean${RESET}"
cargo clean
}
# Check repository for typos # Check repository for typos
check_typos () { check_typos () {
echo -e "\n${PURPLE}check typos${RESET}" echo -e "\n${PURPLE}check typos${RESET}"
+9 -9
View File
@@ -3,12 +3,12 @@ pub mod log_sanitizer {
use cansi::{v3::categorise_text, Color as CansiColor, Intensity}; use cansi::{v3::categorise_text, Color as CansiColor, Intensity};
use ratatui::{ use ratatui::{
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
text::{Span, Spans}, text::{Line, Span},
}; };
/// Attempt to colorize the given string to tui-rs standards /// Attempt to colorize the given string to ratatui standards
pub fn colorize_logs<'a>(input: &str) -> Vec<Spans<'a>> { pub fn colorize_logs<'a>(input: &str) -> Vec<Line<'a>> {
vec![Spans::from( vec![Line::from(
categorise_text(input) categorise_text(input)
.iter() .iter()
.map(|i| { .map(|i| {
@@ -39,17 +39,17 @@ pub mod log_sanitizer {
)] )]
} }
/// Remove all ansi formatting from a given string and create tui-rs spans /// Remove all ansi formatting from a given string and create ratatui Lines
pub fn remove_ansi<'a>(input: &str) -> Vec<Spans<'a>> { pub fn remove_ansi<'a>(input: &str) -> Vec<Line<'a>> {
raw(&categorise_text(input) raw(&categorise_text(input)
.into_iter() .into_iter()
.map(|i| i.text) .map(|i| i.text)
.collect::<String>()) .collect::<String>())
} }
/// create tui-rs spans that exactly match the given strings /// create ratatui Lines that exactly match the given strings
pub fn raw<'a>(input: &str) -> Vec<Spans<'a>> { pub fn raw<'a>(input: &str) -> Vec<Line<'a>> {
vec![Spans::from(Span::raw(input.to_owned()))] vec![Line::from(Span::raw(input.to_owned()))]
} }
/// Change from ansi to tui colors /// Change from ansi to tui colors
+44 -44
View File
@@ -4,7 +4,7 @@ use ratatui::{
layout::{Alignment, Constraint, Direction, Layout, Rect}, layout::{Alignment, Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
symbols, symbols,
text::{Span, Spans}, text::{Line, Span},
widgets::{ widgets::{
Axis, Block, BorderType, Borders, Chart, Clear, Dataset, GraphType, List, ListItem, Axis, Block, BorderType, Borders, Chart, Clear, Dataset, GraphType, List, ListItem,
Paragraph, Paragraph,
@@ -96,7 +96,7 @@ pub fn commands<B: Backend>(
let items = app_data.lock().get_control_items().map_or(vec![], |i| { let items = app_data.lock().get_control_items().map_or(vec![], |i| {
i.iter() i.iter()
.map(|c| { .map(|c| {
let lines = Spans::from(vec![Span::styled( let lines = Line::from(vec![Span::styled(
c.to_string(), c.to_string(),
Style::default().fg(c.get_color()), Style::default().fg(c.get_color()),
)]); )]);
@@ -138,7 +138,7 @@ pub fn containers<B: Backend>(
let state_style = Style::default().fg(i.state.get_color()); let state_style = Style::default().fg(i.state.get_color());
let blue = Style::default().fg(Color::Blue); let blue = Style::default().fg(Color::Blue);
let lines = Spans::from(vec![ let lines = Line::from(vec![
Span::styled( Span::styled(
format!( format!(
"{:<width$}", "{:<width$}",
@@ -489,25 +489,25 @@ pub fn heading_bar<B: Backend>(
/// Help popup box needs these three pieces of information /// Help popup box needs these three pieces of information
struct HelpInfo { struct HelpInfo {
spans: Vec<Spans<'static>>, lines: Vec<Line<'static>>,
width: usize, width: usize,
height: usize, height: usize,
} }
impl HelpInfo { impl HelpInfo {
/// Find the max width of a Span in &[Spans], although it isn't calculating it correctly /// Find the max width of a Span in &[Line], although it isn't calculating it correctly
fn calc_width(spans: &[Spans]) -> usize { fn calc_width(lines: &[Line]) -> usize {
spans lines
.iter() .iter()
.flat_map(|x| x.0.iter()) .flat_map(|x| x.spans.iter())
.map(ratatui::text::Span::width) .map(ratatui::text::Span::width)
.max() .max()
.unwrap_or(1) .unwrap_or(1)
} }
/// Just an empty span, i.e. a new line /// Just an empty span, i.e. a new line
fn empty_span<'a>() -> Spans<'a> { fn empty_span<'a>() -> Line<'a> {
Spans::from(String::new()) Line::from(String::new())
} }
/// generate a span, of given &str and given color /// generate a span, of given &str and given color
@@ -527,15 +527,15 @@ impl HelpInfo {
/// Generate the `oxker` name span + metadata /// Generate the `oxker` name span + metadata
fn gen_name() -> Self { fn gen_name() -> Self {
let mut spans = NAME_TEXT let mut lines = NAME_TEXT
.lines() .lines()
.map(|i| Spans::from(Self::white_span(i))) .map(|i| Line::from(Self::white_span(i)))
.collect::<Vec<_>>(); .collect::<Vec<_>>();
spans.insert(0, Self::empty_span()); lines.insert(0, Self::empty_span());
let width = Self::calc_width(&spans); let width = Self::calc_width(&lines);
let height = spans.len(); let height = lines.len();
Self { Self {
spans, lines,
width, width,
height, height,
} }
@@ -543,15 +543,15 @@ impl HelpInfo {
/// Generate the description span + metadata /// Generate the description span + metadata
fn gen_description() -> Self { fn gen_description() -> Self {
let spans = [ let lines = [
Self::empty_span(), Self::empty_span(),
Spans::from(Self::white_span(DESCRIPTION)), Line::from(Self::white_span(DESCRIPTION)),
Self::empty_span(), Self::empty_span(),
]; ];
let width = Self::calc_width(&spans); let width = Self::calc_width(&lines);
let height = spans.len(); let height = lines.len();
Self { Self {
spans: spans.to_vec(), lines: lines.to_vec(),
width, width,
height, height,
} }
@@ -564,15 +564,15 @@ impl HelpInfo {
let or = || button_desc("or"); let or = || button_desc("or");
let space = || button_desc(" "); let space = || button_desc(" ");
let spans = [ let lines = [
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("tab"), button_item("tab"),
or(), or(),
button_item("shift+tab"), button_item("shift+tab"),
button_desc("to change panels"), button_desc("to change panels"),
]), ]),
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("↑ ↓"), button_item("↑ ↓"),
or(), or(),
@@ -583,40 +583,40 @@ impl HelpInfo {
button_item("Home End"), button_item("Home End"),
button_desc("to change selected line"), button_desc("to change selected line"),
]), ]),
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("enter"), button_item("enter"),
button_desc("to send docker container command"), button_desc("to send docker container command"),
]), ]),
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("h"), button_item("h"),
button_desc("to toggle this help information"), button_desc("to toggle this help information"),
]), ]),
Spans::from(vec![space(), button_item("0"), button_desc("to stop sort")]), Line::from(vec![space(), button_item("0"), button_desc("to stop sort")]),
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("1 - 9"), button_item("1 - 9"),
button_desc("sort by header - or click header"), button_desc("sort by header - or click header"),
]), ]),
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("m"), button_item("m"),
button_desc( button_desc(
"to toggle mouse capture - if disabled, text on screen can be selected & copied", "to toggle mouse capture - if disabled, text on screen can be selected & copied",
), ),
]), ]),
Spans::from(vec![ Line::from(vec![
space(), space(),
button_item("q"), button_item("q"),
button_desc("to quit at any time"), button_desc("to quit at any time"),
]), ]),
]; ];
let height = spans.len(); let height = lines.len();
let width = Self::calc_width(&spans); let width = Self::calc_width(&lines);
Self { Self {
spans: spans.to_vec(), lines: lines.to_vec(),
width, width,
height, height,
} }
@@ -624,22 +624,22 @@ impl HelpInfo {
/// Generate the final lines, GitHub link etc, + metadata /// Generate the final lines, GitHub link etc, + metadata
fn gen_final() -> Self { fn gen_final() -> Self {
let spans = [ let lines = [
Self::empty_span(), Self::empty_span(),
Spans::from(vec![Self::black_span( Line::from(vec![Self::black_span(
"currently an early work in progress, all and any input appreciated", "currently an early work in progress, all and any input appreciated",
)]), )]),
Spans::from(vec![Span::styled( Line::from(vec![Span::styled(
REPO.to_owned(), REPO.to_owned(),
Style::default() Style::default()
.fg(Color::White) .fg(Color::White)
.add_modifier(Modifier::UNDERLINED), .add_modifier(Modifier::UNDERLINED),
)]), )]),
]; ];
let height = spans.len(); let height = lines.len();
let width = Self::calc_width(&spans); let width = Self::calc_width(&lines);
Self { Self {
spans: spans.to_vec(), lines: lines.to_vec(),
width, width,
height, height,
} }
@@ -689,22 +689,22 @@ pub fn help_box<B: Backend>(f: &mut Frame<'_, B>) {
) )
.split(area); .split(area);
let name_paragraph = Paragraph::new(name_info.spans) let name_paragraph = Paragraph::new(name_info.lines)
.style(Style::default().bg(Color::Magenta).fg(Color::White)) .style(Style::default().bg(Color::Magenta).fg(Color::White))
.block(Block::default()) .block(Block::default())
.alignment(Alignment::Center); .alignment(Alignment::Center);
let description_paragraph = Paragraph::new(description_info.spans) let description_paragraph = Paragraph::new(description_info.lines)
.style(Style::default().bg(Color::Magenta).fg(Color::Black)) .style(Style::default().bg(Color::Magenta).fg(Color::Black))
.block(Block::default()) .block(Block::default())
.alignment(Alignment::Center); .alignment(Alignment::Center);
let help_paragraph = Paragraph::new(button_info.spans) let help_paragraph = Paragraph::new(button_info.lines)
.style(Style::default().bg(Color::Magenta).fg(Color::Black)) .style(Style::default().bg(Color::Magenta).fg(Color::Black))
.block(Block::default()) .block(Block::default())
.alignment(Alignment::Left); .alignment(Alignment::Left);
let final_paragraph = Paragraph::new(final_info.spans) let final_paragraph = Paragraph::new(final_info.lines)
.style(Style::default().bg(Color::Magenta).fg(Color::Black)) .style(Style::default().bg(Color::Magenta).fg(Color::Black))
.block(Block::default()) .block(Block::default())
.alignment(Alignment::Center); .alignment(Alignment::Center);
@@ -738,7 +738,7 @@ pub fn delete_confirm<B: Backend>(
.title_alignment(Alignment::Center) .title_alignment(Alignment::Center)
.borders(Borders::ALL); .borders(Borders::ALL);
let confirm = Spans::from(vec![ let confirm = Line::from(vec![
Span::from("Are you sure you want to delete container: "), Span::from("Are you sure you want to delete container: "),
Span::styled( Span::styled(
name, name,
+1 -2
View File
@@ -278,8 +278,7 @@ fn draw_frame<B: Backend>(
); );
if let Some(id) = delete_confirm { if let Some(id) = delete_confirm {
let name = app_data.lock().get_container_name_by_id(&id); app_data.lock().get_container_name_by_id(&id).map_or_else(
name.map_or_else(
|| { || {
// If a container is deleted outside of oxker but whilst the Delete Confirm dialog is open, it can get caught in kind of a dead lock situation // If a container is deleted outside of oxker but whilst the Delete Confirm dialog is open, it can get caught in kind of a dead lock situation
// so if in that unique situation, just clear the delete_container id // so if in that unique situation, just clear the delete_container id