7 Commits

Author SHA1 Message Date
e17db09859 add install 2023-01-22 21:27:24 +01:00
b94e5b3394 fixed common errs 2023-01-22 12:06:04 +01:00
115f1d5db3 removed vscode 2023-01-22 12:05:46 +01:00
845d59040c removed target 2023-01-22 12:05:11 +01:00
936c6b4741 add base cmd 2023-01-22 12:04:41 +01:00
332ef8e00d add pipelines 2023-01-21 20:58:51 +01:00
ebdbd0e8a5 add base package 2023-01-21 15:08:55 +01:00
55 changed files with 1026 additions and 208 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
target/
.vscode/

527
Cargo.lock generated Normal file
View File

@@ -0,0 +1,527 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "backtrace"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "char"
version = "0.1.0"
dependencies = [
"clap",
"color-eyre",
"eyre",
"serde",
"toml",
]
[[package]]
name = "clap"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2"
dependencies = [
"bitflags",
"clap_lex",
"is-terminal",
"strsim",
"termcolor",
]
[[package]]
name = "clap_lex"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
dependencies = [
"os_str_bytes",
]
[[package]]
name = "color-eyre"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
dependencies = [
"backtrace",
"color-spantrace",
"eyre",
"indenter",
"once_cell",
"owo-colors",
"tracing-error",
]
[[package]]
name = "color-spantrace"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ba75b3d9449ecdccb27ecbc479fdc0b87fa2dd43d2f8298f9bf0e59aacc8dce"
dependencies = [
"once_cell",
"owo-colors",
"tracing-core",
"tracing-error",
]
[[package]]
name = "errno"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "eyre"
version = "0.6.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c2b6b5a29c02cdc822728b7d7b8ae1bab3e3b05d44522770ddd49722eeac7eb"
dependencies = [
"indenter",
"once_cell",
]
[[package]]
name = "gimli"
version = "0.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793"
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "indenter"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
[[package]]
name = "indexmap"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "io-lifetimes"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
dependencies = [
"hermit-abi",
"io-lifetimes",
"rustix",
"windows-sys",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "linux-raw-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "object"
version = "0.30.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b8c786513eb403643f2a88c244c2aaa270ef2153f55094587d0c48a3cf22a83"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "os_str_bytes"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "owo-colors"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "proc-macro2"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustix"
version = "0.36.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "serde"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.152"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "sharded-slab"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
dependencies = [
"lazy_static",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termcolor"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
dependencies = [
"winapi-util",
]
[[package]]
name = "thread_local"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"once_cell",
]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"indexmap",
"serde",
]
[[package]]
name = "tracing"
version = "0.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
dependencies = [
"cfg-if",
"pin-project-lite",
"tracing-core",
]
[[package]]
name = "tracing-core"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-error"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d686ec1c0f384b1277f097b2f279a2ecc11afe8c133c1aabf036a27cb4cd206e"
dependencies = [
"tracing",
"tracing-subscriber",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
dependencies = [
"sharded-slab",
"thread_local",
"tracing-core",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
[[package]]
name = "windows_i686_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
[[package]]
name = "windows_i686_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"

13
Cargo.toml Normal file
View File

@@ -0,0 +1,13 @@
[package]
name = "char"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = "4.1.1"
color-eyre = "0.6.2"
eyre = "0.6.8"
serde = { version = "1.0.152", features = ["derive"] }
toml = { version = "0.5.11", features = ["preserve_order"] }

View File

@@ -1,208 +0,0 @@
# Pipelines design docs
The goal of this experiment is to play with various code sharing features. The
pipelines in this experiment is supposed to model normal code sharing behavior
of libraries, with overriding capabilities of the downstream repository
The goal is to split the body of the work in three parts.
- libraries,
- compendiums
- articles
The terminology is as such:
## Libraries
Libraries provide raw functions, and is a general abstraction on an underlying
process, such as running a container, executing a shell script etc. Libraries
might define an API descripting how to interact with it. It is up to the
compendium, and article to use these in a sane manner.
Such that:
```rust
pub fn execute_shell(&self, input: &ShellOpts) -> Result<ShellOutput> {
...
}
```
These work similar to raw primitive functions, but should serve as an
opinionated flyweight. These may be extremely specific, such as building a go
binary, creating a github release etc. The details are left to the caller.
A version scheme of the library should follow semver, as that is the best model
at the moment for versioning. Libraries should be pulled using the native
package manager, or include as a submodule.
## Compendiums
A compendium is an opinionated collection of libraries, which consists of files,
configurations etc. A compendium is to be used by either other compendiums, or
articles. They are not to be used by libraries, this is to provide a natural
hierachy. The end result should be a directed acyclic graph.
A compendium should provide an API for either other compendiums, or articles.
These apis, need to remain flexible, and be open to mutations. As such all
primitive features, files, configurations need to be exposed as raw data or data
structures if suitable.
This is done using pipelines, or middleware for the specific parts. A data
object will pass from above, containing the data to implement the required
interfaces of the Compendium, these must be fulfilled for the construction of
the Compendium, else the compilation should fail.
The caller will have the ability to replace the specifics of the Compendium, by
replacing certain pipelines, or mutating the data. In case of mutations, the
data is only modified for that pipeline and below, if a fork occurs above, then
the divergent paths won't be affected.
Compendiums are driven by pipelines applied to them either from other
compendiums or articles. An article or compendium will only have access to their
direct dependent compendiums pipelines. An article will naturally expose
pipelines to be called by the user.
```rust
pub struct GoApplication;
impl Compendium for GoApplication {
type Input = GoApplicationOpts;
pub fn get_pipelines(&mut self) -> Result<Pipelines> {
let pipelines = self.pipelines
.clone()
.add(self.get_application_pipelines())?
.add(self.get_go_releaser_pipelines())?;
Ok(pipelines)
}
}
```
## Articles
An article is a specific implementation of a compendium, it is the end of the
chain, and is meant to be directly executed by the user, using a client
application.
It by default is supposed to be a golden path, I.e. it passes the defaults of
the Compendium, but on a case-by-case basis has the ability to modify its
pipelines to its needs. This may be changing certain default configurations,
mutate a dockerfile, add additional steps to a pipeline etc, and remove others.
We reason that once you stray from the golden path, you should be in control,
this may be done by forking the compendium's features.
It provides pipelines as actions, and implements a strict protocol for
communication.
```rust
pub struct MyGoService;
impl Article for MyGoService {
fn get_pipelines(&mut self) -> Result<Pipelines> {
let mut go_pipelines = GoApplication::new().get_pipelines()?;
let api_pipeline = self.get_api_pipeline()?;
let build_pipeline = self.get_docker_pipeline(go_pipelines.extract::<BuildPipeline>()?)?;;
let pipelines = PipelineBuilder::new()
.append(go_pipelines)
.append(api_pipeline)
.append(build_pipeline)
.build()?
Ok(pipelines)
}
}
```
## Usage
A host app can now call these:
```bash
char ls
```
ls simply displays the information on what pipeline are available
```bash
char run build
```
run build will execute the pipeline build. It will validate input available from
char.toml, push these keys/values through to the pipeline, which will go through
all the steps.
- build
- MyGoService
- DockerBuildPipeline
- (BuildPipeline)
- DockerLibrary
- `fn docker_build(dockerfile_contents: string)`
- Native dependencies
- "write dockerfile /tmp/abc/dockerfile"
- "shell -> docker build -f /tmp/abc/dockerfile some-library-path"
## Common scenarios
### Replacing parts of a build script (dockerfile)
A compendium may embed/provide a dockerfile or any other resource, these are
provided through consistent interfaces.
```rust
pub struct GoDockerBuildPipeline;
impl GoDockerBuildPipeline {
fn get_resources(&self) -> Result<(
libraries::docker::DockerContents,
libraries::docker::DockerBuildTags)> {
return (self.contents, self.build_tags)
}
fn mutate_resources(
&mut self,
contents: libraries::docker::DockerContents,
build_tags: libraries::docker::DockerBuildTags,
) -> Result<()> {
self.contents = contents;
self.build_tags = build_tags
}
}
impl BuildPipeline for GoDockerBuildPipeline {
fn execute(&mut self, config: Configuration) -> Result<()> {
let (docker_contents, base_tags) = self.get_resources()
libraries::docker::build(docker_contents, base_tags, config)
}
}
```
In the article you can now replace the resources to fit your needs, that or
building your own pipeline.
```rust
pub struct MyGoService;
impl Article for MyGoService {
fn get_pipelines(&mut self) -> Result<Pipelines> {
let go_app = GoApplication::new();
let go_pipelines = go_app.get_pipelines();
let mut go_build_pipeline = go_pipelines.get_pipeline::<GoDockerBuildPipeline>()?;
let go_resources = go_build_pipeline.get_resources()?;
let go_resources = self.mutate_go_resources(&go_resources)?;
go_build_pipeline.mutate_resources(go_resources)?;
go_pipelines.replace::<GoDockerBuildPipeline>(go_build_pipeline)?;
let pipelines = PipelineBuilder::new()
.append(.get_pipelines())
.build()?
Ok(pipelines)
}
}
```

View File

@@ -0,0 +1,55 @@
[char]
plan = "plans/base/"
dependencies = ["plans/extension"]
[char.overrides]
org = "overrides/org"
[application]
name = "service"
[config]
# provides both local and k8s by default can also be set using:
# config.k8s.rabbitmq = true
# config.docker-compose.rabbitmq = true
rabbitmq = true
postgres = true
[config.org]
squad = "kjuulh"
domain = "tooling"
[config.pipeline]
path = "char/ci/" # most of these are default, showing them here as a showcase
[config.actions]
path = "char/actions"
[config.releaser]
type = "rust-releaser"
[config.cargo]
crates = ["crates/service_core", "crates/service_util"]
[config.rust_bin]
name = "service"
logging = { pretty = true }
[config.environments.local]
type = "docker-compose" # technically default
[config.environments.local.env]
"env" = "local"
"db.hostname" = "postgres"
"db.secret" = "postgres"
[config.k8s]
monitoring = true
[config.environments.dev]
type = "k8s"
[config.environments.local.dev]
"env" = "local"
"db.hostname" = "service-db"
"db.secret" = { type = "secret" }

View File

@@ -0,0 +1,8 @@
[package]
name = "actions"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

View File

@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "org"
version = "0.1.0"

View File

@@ -0,0 +1,8 @@
[package]
name = "org"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

View File

@@ -0,0 +1 @@
{"rustc_fingerprint":13769919407148446586,"outputs":{"10376369925670944939":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n/Users/kah/.rustup/toolchains/stable-aarch64-apple-darwin\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"aarch64\"\ntarget_endian=\"little\"\ntarget_env=\"\"\ntarget_family=\"unix\"\ntarget_feature=\"aes\"\ntarget_feature=\"crc\"\ntarget_feature=\"dit\"\ntarget_feature=\"dotprod\"\ntarget_feature=\"dpb\"\ntarget_feature=\"dpb2\"\ntarget_feature=\"fcma\"\ntarget_feature=\"fhm\"\ntarget_feature=\"flagm\"\ntarget_feature=\"fp16\"\ntarget_feature=\"frintts\"\ntarget_feature=\"jsconv\"\ntarget_feature=\"lor\"\ntarget_feature=\"lse\"\ntarget_feature=\"neon\"\ntarget_feature=\"paca\"\ntarget_feature=\"pacg\"\ntarget_feature=\"pan\"\ntarget_feature=\"pmuv3\"\ntarget_feature=\"ras\"\ntarget_feature=\"rcpc\"\ntarget_feature=\"rcpc2\"\ntarget_feature=\"rdm\"\ntarget_feature=\"sb\"\ntarget_feature=\"sha2\"\ntarget_feature=\"sha3\"\ntarget_feature=\"ssbs\"\ntarget_feature=\"vh\"\ntarget_has_atomic=\"128\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"macos\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"apple\"\nunix\n","stderr":""},"15697416045686424142":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.dylib\nlib___.dylib\nlib___.a\nlib___.dylib\n","stderr":""},"4614504638168534921":{"success":true,"status":"","code":0,"stdout":"rustc 1.66.0 (69f9c33d7 2022-12-12)\nbinary: rustc\ncommit-hash: 69f9c33d71c871fc16ac445211281c6e7a340943\ncommit-date: 2022-12-12\nhost: aarch64-apple-darwin\nrelease: 1.66.0\nLLVM version: 15.0.2\n","stderr":""}},"successes":{}}

View File

@@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

View File

@@ -0,0 +1 @@
{"rustc":15520539443732555526,"features":"[]","target":10808372008975436347,"profile":11736316127369858332,"path":1684066648322511884,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/org-2413d5d1cd4f3ae1/dep-bin-org"}}],"rustflags":[],"metadata":7797948686568424061,"config":2202906307356721367,"compile_kind":0}

View File

@@ -0,0 +1 @@
This file has an mtime of when this was started.

View File

@@ -0,0 +1,5 @@
/Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/target/debug/deps/org-2413d5d1cd4f3ae1: src/main.rs
/Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/target/debug/deps/org-2413d5d1cd4f3ae1.d: src/main.rs
src/main.rs:

Binary file not shown.

View File

@@ -0,0 +1 @@
/Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/target/debug/org: /Users/kah/git/git.front.kjuulh.io/kjuulh/char/examples/service/char/overrides/org/src/main.rs

View File

@@ -0,0 +1,5 @@
[char]
[plan]
name = "base"

44
src/cli.rs Normal file
View File

@@ -0,0 +1,44 @@
use std::path::PathBuf;
use crate::{
deps,
resolvers::{install, Resolver},
};
pub struct Cli {
deps: deps::Deps,
install: Box<dyn Resolver + Send + Sync>,
}
impl Cli {
pub fn new(deps: deps::Deps) -> eyre::Result<Self> {
Ok(Self {
deps: deps.clone(),
install: install::Install::new(deps),
})
}
pub fn matches(self, args: &[&str]) -> eyre::Result<()> {
let mut cli = clap::Command::new("char")
.arg(clap::Arg::new("path").long("path").short('p'))
.subcommand(self.install.cmd()?);
let matches = cli.clone().get_matches_from(args);
let path = matches.get_one::<String>("path");
if let Some(p) = path {
let path = PathBuf::from(p);
if !path.exists() {
eyre::bail!("no char.toml exists at --path")
}
self.deps.parser.set_path(path);
}
match matches.subcommand() {
Some(("install", args)) => self.install.matches(args)?,
_ => cli.print_help()?,
}
Ok(())
}
}

29
src/context/mod.rs Normal file
View File

@@ -0,0 +1,29 @@
use crate::models::Char;
pub struct Context {}
impl Context {
pub fn new(chars: Vec<Char>) -> Self {
Self {}
}
}
pub struct ContextBuilder {
chars: Vec<Char>,
}
impl ContextBuilder {
pub fn new() -> Self {
Self { chars: vec![] }
}
pub fn add_char(mut self, char: &Char) -> Self {
self.chars.push(char.clone());
self
}
pub fn build(self) -> Context {
Context::new(self.chars)
}
}

33
src/deps.rs Normal file
View File

@@ -0,0 +1,33 @@
use std::{ops::Deref, sync::Arc};
use crate::{parser::Parser, services::downloader::Downloader};
#[derive(Debug, Clone)]
pub struct Deps {
inner: Arc<InnerDeps>,
}
#[derive(Debug, Clone)]
pub struct InnerDeps {
pub parser: Parser,
pub downloader: Downloader,
}
impl Default for Deps {
fn default() -> Self {
let parser = Parser::default();
let downloader = Downloader::new(parser.clone());
Self {
inner: Arc::new(InnerDeps { parser, downloader }),
}
}
}
impl Deref for Deps {
type Target = Arc<InnerDeps>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}

32
src/main.rs Normal file
View File

@@ -0,0 +1,32 @@
pub mod cli;
mod deps;
mod models;
mod parser;
mod resolvers;
mod services;
mod context;
fn main() -> eyre::Result<()> {
color_eyre::install()?;
let args = std::env::args();
let deps = deps::Deps::default();
let c = cli::Cli::new(deps)?;
c.matches(
args.collect::<Vec<String>>()
.iter()
.map(|s| s.as_str())
.collect::<Vec<&str>>()
.as_slice(),
)?;
let p = std::path::PathBuf::from("examples/service/char.toml");
let char = std::fs::read_to_string(p)?.parse::<models::Char>()?;
dbg!(char);
Ok(())
}

48
src/models.rs Normal file
View File

@@ -0,0 +1,48 @@
use std::collections::BTreeMap;
use serde::{Deserialize, Serialize};
type Overrides = BTreeMap<String, String>;
type Dependencies = Vec<String>;
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Conf {
pub plan: String,
pub dependencies: Option<Dependencies>,
pub overrides: Option<Overrides>,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Application {
name: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct Plan {
name: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[serde(untagged)]
pub enum Char {
Application {
char: Option<Conf>,
application: Application,
config: BTreeMap<String, toml::Value>,
},
Plan {
char: Option<Conf>,
plan: Plan,
config: BTreeMap<String, toml::Value>,
},
}
impl std::str::FromStr for Char {
type Err = eyre::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let t: Char = toml::from_str(s)?;
Ok(t)
}
}

62
src/parser.rs Normal file
View File

@@ -0,0 +1,62 @@
use std::{
path::PathBuf,
sync::{Arc, RwLock},
};
use eyre::Context;
use crate::models::{self, Char};
#[derive(Debug, Clone)]
pub struct Parser {
path: Arc<RwLock<Option<PathBuf>>>,
}
impl Parser {
pub fn new(path: PathBuf) -> Self {
Self {
path: Arc::new(RwLock::new(Some(path))),
}
}
pub fn set_path(&self, path: PathBuf) {
let mut writer = self.path.write().unwrap();
*writer = Some(path);
}
pub fn get_path(&self) -> eyre::Result<PathBuf> {
let read_path = self.path.read().unwrap();
let path = match read_path.clone() {
Some(p) => p,
None => todo!(), // find using git later on
};
Ok(path)
}
pub fn parse(&self) -> eyre::Result<models::Char> {
let mut path = self.get_path()?;
if !path.ends_with("char.toml") {
path.push("char.toml")
}
let contents =
std::fs::read_to_string(&path).context("char.toml doesn't exist at that path")?;
contents.parse::<Char>()
}
pub fn parse_from(&self, path: &PathBuf) -> eyre::Result<models::Char> {
let contents =
std::fs::read_to_string(path).context("char.toml doesn't exist at that path")?;
contents.parse::<Char>()
}
}
impl Default for Parser {
fn default() -> Self {
Self {
path: Arc::new(RwLock::new(None)),
}
}
}

29
src/resolvers/install.rs Normal file
View File

@@ -0,0 +1,29 @@
use crate::deps;
use super::{DynResolver, Resolver};
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Install {
deps: deps::Deps,
}
impl Install {
pub fn new(deps: deps::Deps) -> DynResolver {
Box::new(Self { deps })
}
}
impl Resolver for Install {
fn cmd(&self) -> eyre::Result<clap::Command> {
let install = clap::Command::new("install");
Ok(install)
}
fn matches(&self, _args: &clap::ArgMatches) -> eyre::Result<()> {
self.deps.downloader.download()?;
Ok(())
}
}

8
src/resolvers/mod.rs Normal file
View File

@@ -0,0 +1,8 @@
pub(crate) mod install;
pub trait Resolver {
fn cmd(&self) -> eyre::Result<clap::Command>;
fn matches(&self, args: &clap::ArgMatches) -> eyre::Result<()>;
}
pub type DynResolver = Box<dyn Resolver + Send + Sync>;

View File

@@ -0,0 +1,96 @@
use std::{fs::canonicalize, path::PathBuf};
use crate::{
context::{Context, ContextBuilder},
models::{Char, Conf},
parser::Parser,
};
#[derive(Debug, Clone)]
pub struct Downloader {
parser: Parser,
}
#[allow(dead_code)]
impl Downloader {
pub fn new(parser: Parser) -> Self {
Self { parser }
}
/// Unfolds char
/// 1. Download path
/// 2. Parse char in downloaded path
/// 3. Repeat from 1. until there are no more parents
pub fn download(&self) -> eyre::Result<Context> {
let mut context_builder = ContextBuilder::new();
let char = self.parser.parse()?;
context_builder = context_builder.add_char(&char);
let first_char_path = self.parser.get_path()?;
let mut root = std::env::current_dir()?;
root = root.join(&first_char_path);
root.push(".char");
let output = self.create_output_dir(&root)?;
let mut parent_char = char;
let path = first_char_path;
loop {
parent_char = match &parent_char {
Char::Application {
char,
application: _,
config: _,
} => match char {
Some(c) => self.download_plan(c, &path, &output)?,
None => {
break;
}
},
Char::Plan {
char,
plan: _,
config: _,
} => match char {
Some(_c) => todo!(),
None => {
break;
}
},
}
}
Ok(context_builder.build())
}
fn download_plan(
&self,
conf: &Conf,
path: &PathBuf,
output_path: &PathBuf,
) -> eyre::Result<Char> {
let plan = &conf.plan;
// TODO: decide whether it is a file or a git repo
// TODO: Starting with files only, as such implement git repo later
let path_buf = std::path::PathBuf::from(plan);
let path = path.join(path_buf);
if !path.exists() {
eyre::bail!("path doesn't exist: {}", path.to_string_lossy())
}
let path = canonicalize(path)?;
dbg!(path);
dbg!(output_path);
todo!()
}
fn create_output_dir(&self, root: &PathBuf) -> eyre::Result<PathBuf> {
let mut output = root.clone();
output.push("plans");
std::fs::create_dir_all(&output)?;
Ok(output)
}
}

1
src/services/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod downloader;