Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: CI
on:
pull_request:
types:
- opened
- edited
- reopened
- synchronize

env:
CARGO_TERM_COLOR: always
RUST_TARGET: x86_64-unknown-linux-musl

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and test
uses: gmiam/rust-musl-action@master
with:
args: make all
118 changes: 118 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: release

on:
push:
tags:
- v[0-9]+.[0-9]+.[0-9]+*
workflow_dispatch:

env:
CARGO_TERM_COLOR: always
RUST_TARGET: x86_64-unknown-linux-musl
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build toml cli
# uses: juankaram/rust-musl-action@master
uses: gmiam/rust-musl-action@master
with:
args: cargo build --target $RUST_TARGET --release
- name: store-artifacts
uses: actions/upload-artifact@v2
with:
if-no-files-found: error
name: toml-artifacts-linux
path: |
target/${{ env.RUST_TARGET }}/release/toml

prepare-tarball-linux:
runs-on: ubuntu-latest
needs: [build-linux]
steps:
- name: download artifacts
uses: actions/download-artifact@v2
with:
name: toml-artifacts-linux
path: toml-cli
- name: prepare release tarball
run: |
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
tarball="toml-cli-$tag-linux-amd64.tgz"
chmod +x toml-cli/*
tar cf - toml-cli | gzip > ${tarball}
echo "tarball=${tarball}" >> $GITHUB_ENV

shasum="$tarball.sha256sum"
sha256sum $tarball > $shasum
echo "tarball_shasum=${shasum}" >> $GITHUB_ENV
- name: store-artifacts
uses: actions/upload-artifact@v2
with:
name: release-tarball
path: |
${{ env.tarball }}
${{ env.tarball_shasum }}

create-release:
runs-on: ubuntu-latest
needs: [prepare-tarball-linux]
steps:
- name: download artifacts
uses: actions/download-artifact@v2
with:
name: release-tarball
path: tarballs
- name: prepare release env
run: |
echo "tarballs<<EOF" >> $GITHUB_ENV
for I in $(ls tarballs);do echo "tarballs/${I}" >> $GITHUB_ENV; done
echo "EOF" >> $GITHUB_ENV
tag=$(echo $GITHUB_REF | cut -d/ -f3-)
echo "tag=${tag}" >> $GITHUB_ENV
cat $GITHUB_ENV
- name: push release
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
with:
name: "Toml cli ${{ env.tag }}"
body: |
"Toml cli release ${{ env.tag }}"
generate_release_notes: true
files: |
${{ env.tarballs }}

publish-image:
runs-on: ubuntu-latest
needs: [build-linux]
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Log in to the container registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: download artifacts
uses: actions/download-artifact@v2
with:
name: toml-artifacts-linux
path: misc
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: build and push toml cli image
uses: docker/build-push-action@v3
with:
context: misc
file: misc/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
51 changes: 51 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ serde = "1.0"
serde_json = "1.0"
structopt = "0.3"
toml_edit = "0.15"

[dev-dependencies]
tempfile = "3.3.0"
31 changes: 31 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
default: build

CARGO ?= $(shell which cargo)
RUST_TARGET ?= x86_64-unknown-linux-musl
INSTALL_DIR_PREFIX ?= "/usr/local/bin"

.format:
${CARGO} fmt -- --check

build: .format
${CARGO} build --target ${RUST_TARGET} --release
# Cargo will skip checking if it is already checked
${CARGO} clippy --bins --tests -- -Dwarnings

install: .format build
@sudo mkdir -m 755 -p $(INSTALL_DIR_PREFIX)
@sudo install -m 755 target/${RUST_TARGET}/release/toml $(INSTALL_DIR_PREFIX)/toml

clean:
${CARGO} clean

ut:
RUST_BACKTRACE=1 ${CARGO} test --workspace -- --skip integration --nocapture

integration:
# run tests under `test` directory
RUST_BACKTRACE=1 ${CARGO} test --workspace -- integration --nocapture

test: ut integration

all: build install test
4 changes: 4 additions & 0 deletions misc/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM alpine:3.17

ADD toml /bin/toml
RUN chmod +x /bin/toml
87 changes: 73 additions & 14 deletions test/test.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,82 @@
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::fs;
use std::process;
use std::str;

const TOML_CMD: &str = "toml";

#[test]
fn help_if_no_args() {
fn integration_test_help_if_no_args() {
// Probably want to factor out much of this when adding more tests.
let proc = process::Command::new(get_exec_path()).output().unwrap();
assert!(!proc.status.success());
let stderr = str::from_utf8(proc.stderr.as_slice()).unwrap();
let cmd = process::Command::new(TOML_CMD).output().unwrap();
assert!(!cmd.status.success());
let stderr = str::from_utf8(cmd.stderr.as_slice()).unwrap();
assert!(stderr.contains("-h, --help"));
}

fn get_exec_path() -> PathBuf {
// TODO is there no cleaner way to get this from Cargo?
// Also should it really be "debug"?
let target_dir: PathBuf = env::var_os("CARGO_TARGET_DIR")
.unwrap_or_else(|| OsString::from("target"))
.into();
target_dir.join("debug").join("toml")
#[test]
fn integration_test_cmd_get() {
let body = r#"[a]
b = "c"
[x]
y = "z""#;
let toml_dir = tempfile::tempdir().expect("failed to create tempdir");
let toml_file = toml_dir.path().join("test.toml");
fs::write(&toml_file, body).expect("failed to write tempfile");
let toml_file = toml_file.as_os_str().to_str().unwrap();

let cmd = process::Command::new(TOML_CMD)
.args(["get", toml_file, "x.y"])
.output()
.unwrap();
assert!(cmd.status.success());
let stdout = str::from_utf8(cmd.stdout.as_slice()).unwrap();
assert_eq!("\"z\"\n", stdout);

// x.z does not exists
let cmd = process::Command::new(TOML_CMD)
.args(["get", toml_file, "x.z"])
.output()
.unwrap();
assert!(!cmd.status.success());
}

#[test]
fn integration_test_cmd_set() {
// fn set(path: PathBuf, query: &str, value_str: &str, opts: SetOpts) -> Result<(), Error> {
let body = r#"[a]
b = "c"
[x]
y = "z""#;
let toml_dir = tempfile::tempdir().expect("failed to create tempdir");
let toml_file = toml_dir.path().join("test.toml");
fs::write(&toml_file, body).expect("failed to write tempfile");
let toml_file = toml_file.as_os_str().to_str().unwrap();

// x.y exists
let cmd = process::Command::new(TOML_CMD)
.args(["set", toml_file, "x.y", "new"])
.output()
.unwrap();
assert!(cmd.status.success());
let stdout = str::from_utf8(cmd.stdout.as_slice()).unwrap();
let excepted = r#"[a]
b = "c"
[x]
y = "new"
"#;
assert_eq!(excepted, stdout);

let cmd = process::Command::new(TOML_CMD)
.args(["set", toml_file, "x.z", "123"])
.output()
.unwrap();
assert!(cmd.status.success());
let stdout = str::from_utf8(cmd.stdout.as_slice()).unwrap();
let excepted = r#"[a]
b = "c"
[x]
y = "z"
z = "123"
"#;
assert_eq!(excepted, stdout);
}