commit 0c265ad7c959c517dd4eceb70213fba267474f9a
parent b91970d6142590aaaecdd47ff2e8c09f79189f5c
Author: arjoonn <arjoonn@midpathsoftware.com>
Date: Thu, 26 Feb 2026 09:08:28 +0000
Render readme (!7)
Reviewed-on: https://gitea.midpathsoftware.com/midpath/jayporeci/pulls/7
Co-authored-by: arjoonn <arjoonn@midpathsoftware.com>
Co-committed-by: arjoonn <arjoonn@midpathsoftware.com>
Diffstat:
4 files changed, 112 insertions(+), 45 deletions(-)
diff --git a/README.md b/README.md
@@ -1,44 +1,36 @@
-# Jaypore CI
+# Documentation
-> Minimal, Offline, Local CI system.
+> Jaypore CI: Minimal, Offline, Local CI system.
-## Installation
+## Install
```bash
-go build -o git-jci ./cmd/git-jci
+# Download an appropriate binary from www.jayporeci.in
+# After that move it to some location on your PATH
sudo mv git-jci /usr/local/bin/
```
-The binary is fully static (no dependencies) and works on any Linux system.
+The binary is fully static (no dependencies) and works on most systems. If you are having issues, please contact us.
+Once installed, git will automatically find it as a subcommand and you can start using it via `git jci run`
-Once installed, git will automatically find it as a subcommand:
+## Config
-```bash
-git jci run
-```
+Create a `.jci` folder in your repository. You can place a `run.sh` file and a `crontab` file in it.
-## Setup
+> Make sure that run.sh is executable!
-Create a `.jci/run.sh` script in your repository:
-
-```bash
-mkdir -p .jci
-cat > .jci/run.sh << 'EOF'
-#!/bin/bash
-set -e
+```
+.jci/
+├── crontab
+└── run.sh
+```
-echo "Running tests..."
-cd "$JCI_REPO_ROOT" && go test ./...
+You can put anything in `run.sh`. Call a python program / run docker commands / replace it with a binary from a rust project that does something else entirely!
-echo "Building..."
-cd "$JCI_REPO_ROOT" && go build -o "$JCI_OUTPUT_DIR/binary" ./cmd/...
+`crontab` is used to schedule things. You can run things like midnight tests / builds, SLA checks, repo auto-commits, repo time trackers etc.
-echo "Done!"
-EOF
-chmod +x .jci/run.sh
-```
-### Environment Variables
+## Environment Vars
Your `run.sh` script has access to:
@@ -50,7 +42,7 @@ Your `run.sh` script has access to:
The script runs with `cwd` set to `JCI_OUTPUT_DIR`. Any files created there become CI artifacts.
-## Minimal workflow
+## Example workflow
```bash
cd repo-dir && git status # enter the repository and check the working tree
@@ -76,32 +68,48 @@ part of the git repository.
- They are garbage collected when the original commit is gone (via `prune`)
- Each commit's CI output is stored as a separate commit object
-## Use cases
-
-- [ ] Automate unit, integration, and end-to-end test suites on every commit
-- [ ] Run linting and static analysis to enforce coding standards
-- [ ] Produce code coverage reports and surface regressions
-- [ ] Build, package, and archive release artifacts across target platforms
-- [ ] Perform dependency and source code security scans (SCA/SAST)
-- [ ] Execute performance and regression benchmarks with historical comparisons
-- [ ] Generate documentation sites and preview environments for review
-- [ ] Validate infrastructure-as-code changes and deployment pipelines via dry runs
-- [ ] Schedule recurring workflows (cron-style) for maintenance tasks
-- [ ] Notify developers and stakeholders when CI statuses change or regress
-
-
-## Platform features
+## FAQ / Needs / Wants / Todos
- [x] Complex pipeline definitions
+ - `run.sh` can be an executable. Do whatever you like!
- [x] Artifacts
+ - Anything in `JCI_OUTPUT_DIR` is an artifact!
- [x] Debug CI locally
+ - Just execute `run.sh` locally.
+- [x] Automate unit, integration, and end-to-end test suites on every commit
+ - Link [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) and run CI whenever you want.
+ - For integration / end to end, I like to use a docker-compose that will compose up services / databases etc, and one container is a test driver like [locust](https://locust.io/).
+- [x] Run linting and static analysis to enforce coding standards
+ - Link [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) and run CI whenever you want.
+- [x] Produce code coverage reports and surface regressions
+ - Outputs are placed in `JCI_OUTPUT_DIR`. We can put HTML coverage reports here if needed and view via CI browser.
+ - For regressions, the `run.sh` can commit examples created by things like
+ [hypothesis](https://hypothesis.readthedocs.io/en/latest/) back to the
+ repo. This ensures that next runs will use those examples and test for
+ regresssions.
+- [x] Build, package, and archive release artifacts across target platforms
+ - I like building a docker image, building stuff inside that, then publishing.
+ - Refer to the [scripts/](http://127.0.0.1:8000/releases/files.html) files for examples on how to build/render etc.
+- [x] Perform dependency and source code security scans (SCA/SAST)
+ - I like to run [Truffle Hog](https://github.com/trufflesecurity/trufflehog) to prevent accidental leaks.
+- [x] Generate documentation sites and preview environments for review
+ - This Jaypore CI site itself is generated and published via CI.
+- [x] Schedule recurring workflows (cron-style) for maintenance tasks
+ - I run a nightly build via cron to ensure that I catch any dependency failures / security breaks. See [.jci/crontab](.jci/crontab.html) for an example.
+- [x] Notify developers and stakeholders when CI statuses change or regress
+ - As part of our scripts, we can call telegram / slack / email APIs and inform devs of changes.
+- [ ] Built-in secrets management with masking, rotation, and per-environment scoping
+ - I currently use [Mozilla SOPS](https://github.com/getsops/sops) for secrets but this might change in the future.
- [ ] Build farms / remote runners on cloud
- [ ] Community / marketplace runners contributed by external teams
- [ ] Shared runner pools across repositories and organizations
- [ ] Deploy keys / scoped access tokens so runners can securely pull & push repos
-- [ ] Built-in secrets management with masking, rotation, and per-environment scoping
- [ ] Merge request / PR status reporting, required-check gating, and review UIs
+ - It would be great to have some integration into PRs so that we can know if our colleagues have run CI jobs or not.
- [ ] Line-by-line coverage overlays and annotations directly on PR/MR diffs
+ - This might be hard since it will depend a LOT on which remote is being used. Gitlab uses a cobertura file but others might not.
- [ ] Deployment environments with history, approvals, and promotion policies
- [ ] First-class integration with observability / error tracking tools (e.g., Sentry)
- [ ] Ecosystem of reusable actions/tasks with versioned catalogs and templates
+ - This is already there? Not sure if this is something we even need to solve?
+- [ ] Validate infrastructure-as-code changes and deployment pipelines via dry runs
diff --git a/scripts/build_image.sh b/scripts/build_image.sh
@@ -12,7 +12,7 @@ echo "Building Docker image '${IMAGE_NAME}'..."
# The repo is NOT baked into the image; it is mounted at runtime via -v.
docker build -t "${IMAGE_NAME}" - <<'DOCKERFILE'
FROM alpine:latest
-RUN apk add --no-cache git ca-certificates stagit bash
+RUN apk add --no-cache git ca-certificates stagit bash lowdown
WORKDIR /work
CMD ["/bin/sh"]
DOCKERFILE
diff --git a/scripts/build_site.sh b/scripts/build_site.sh
@@ -31,6 +31,51 @@ cp -r "${REPO_DIR}/bin" "${PUBLIC_DIR}/binaries"
(cd "${BUILD_DIR}" && pwd && stagit -u /releases/git "${REPO_DIR}")
cp -r "${BUILD_DIR}/." "${RELEASES_DIR}"
+# Render README.md to HTML and replace the stagit-generated content
+README_SRC="${REPO_DIR}/README.md"
+README_DST="${RELEASES_DIR}/file/README.md.html"
+if [[ -f "${README_SRC}" && -f "${README_DST}" ]]; then
+ echo "Rendering README.md to HTML via lowdown..."
+ README_RENDERED="$(mktemp)"
+ lowdown -o "${README_RENDERED}" "${README_SRC}"
+ echo "Injecting rendered README into ${README_DST}"
+ README_TMP_OUTPUT="$(mktemp)"
+ awk -v rendered="${README_RENDERED}" '
+BEGIN {
+ in_content = 0
+ inserted = 0
+}
+{
+ if (!inserted && $0 ~ /<div id="content">/) {
+ print
+ while ((getline line < rendered) > 0) {
+ print line
+ }
+ close(rendered)
+ in_content = 1
+ inserted = 1
+ next
+ }
+ if (in_content) {
+ if ($0 ~ /<\/div>/) {
+ print $0
+ in_content = 0
+ }
+ next
+ }
+ print
+}
+END {
+ if (!inserted) {
+ print "Failed to inject rendered README: <div id=\"content\"> not found" > "/dev/stderr"
+ exit 1
+ }
+}
+' "${README_DST}" > "${README_TMP_OUTPUT}"
+ mv "${README_TMP_OUTPUT}" "${README_DST}"
+ rm -f "${README_RENDERED}"
+fi
+
# Clean up the temporary description file
rm -f "${REPO_DIR}/description"
rm -rf "${REPO_DIR}/binaries"
diff --git a/www_jci/public/assets/git.style.css b/www_jci/public/assets/git.style.css
@@ -42,6 +42,15 @@ img, h1, h2 {
vertical-align: middle;
}
+blockquote {
+ margin: 0px;
+ border: 5px solid var(--line);
+ border-top: 0px;
+ border-right: 0px;
+ border-bottom: 0px;
+ border-radius: 2px;
+ padding: 2px 5px;
+}
img {
border: 0;
}
@@ -92,6 +101,7 @@ a.line {
}
/* ── tables ── */
+
table {
width: 100%;
border-collapse: collapse;
@@ -114,6 +124,7 @@ table td {
#content table td {
vertical-align: top;
white-space: nowrap;
+ border: 1px solid var(--line);
}
#branches tr:hover td,
@@ -164,9 +175,12 @@ code, pre {
padding: 2px 4px;
border-radius: 2px;
}
+pre code {
+ padding: 0px;
+}
pre {
- padding: 1rem 0px;
+ padding: 5px 5px;
border-radius: 6px;
overflow-x: auto;
line-height: 1.55;