Skip to content
This repository was archived by the owner on Jul 19, 2026. It is now read-only.

Commit 460d276

Browse files
authored
Merge pull request #2 from kettle-rb/feat/release-prep
2 parents 2977ce7 + b628b12 commit 460d276

123 files changed

Lines changed: 15421 additions & 2372 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
#!/bin/sh
2-
apt-get update -y
2+
set -e # Exit on error
33

4-
# Basic, commonly needed, dependencies of Ruby & JRuby projects
4+
# Install basic development dependencies for Ruby & JRuby projects
5+
apt-get update -y
56
apt-get install -y direnv default-jdk git zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev
67

7-
# Support for PostgreSQL
8+
# Support for PostgreSQL (commented out by default)
89
# apt-get install -y postgresql libpq-dev
910

11+
# NOTE: Tree-sitter setup is NOT done here because the workspace is not mounted yet
12+
# during the devcontainer build phase. Tree-sitter setup happens in postCreateCommand
13+
# after the workspace is mounted. See devcontainer.json for details.
14+
# This gem needs ALL grammars for fenced code block merging (handled by setup-tree-sitter.sh).
15+
16+
echo "Basic apt packages installed. Tree-sitter will be set up after workspace mount."
17+
1018
# Adds the direnv setup script to ~/.bashrc file (at the end)
1119
echo 'eval "$(direnv hook bash)"' >> ~/.bashrc

.devcontainer/devcontainer.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
// "forwardPorts": [],
1515

1616
// Use 'postCreateCommand' to run commands after the container is created.
17-
"postCreateCommand": "bundle update --bundler",
17+
// First setup tree-sitter (auto-detects sudo requirement), then run bundle as the regular user
18+
// Use ${containerWorkspaceFolder} to get the actual workspace path in the container
19+
"postCreateCommand": "bash ${containerWorkspaceFolder}/.devcontainer/scripts/setup-tree-sitter.sh --workspace=${containerWorkspaceFolder} && bundle update --bundler",
1820

1921
// Configure tool-specific properties.
2022
"customizations" : {
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Setup script for tree-sitter dependencies (Ubuntu/Debian)
5+
# Works for both GitHub Actions and devcontainer environments
6+
#
7+
# Dual-Environment Design:
8+
# - GitHub Actions: Runs as non-root user, auto-detects need for sudo
9+
# - Devcontainer: Can run as root (apt-install feature) or non-root (postCreateCommand)
10+
# - Auto-detection: Checks if running as root (id -u = 0), uses sudo if non-root
11+
#
12+
# This script installs ALL tree-sitter grammars for integration testing
13+
#
14+
# Options:
15+
# --sudo: Force use of sudo (optional, auto-detected by default)
16+
# --cli: Install tree-sitter-cli via npm (optional)
17+
# --build: Build and install the tree-sitter C runtime from source when distro packages are missing (optional)
18+
# --workspace PATH: Workspace root path for informational/debugging purposes only (defaults to /workspaces/tree_haver)
19+
20+
SUDO=""
21+
INSTALL_CLI=false
22+
BUILD_FROM_SOURCE=false
23+
WORKSPACE_ROOT="/workspaces/markly-merge"
24+
25+
# Parse arguments properly using while loop
26+
while [[ $# -gt 0 ]]; do
27+
case $1 in
28+
--sudo)
29+
SUDO="sudo"
30+
shift
31+
;;
32+
--cli)
33+
INSTALL_CLI=true
34+
shift
35+
;;
36+
--build)
37+
BUILD_FROM_SOURCE=true
38+
shift
39+
;;
40+
--workspace)
41+
WORKSPACE_ROOT="$2"
42+
shift 2
43+
;;
44+
--workspace=*)
45+
WORKSPACE_ROOT="${1#*=}"
46+
shift
47+
;;
48+
*)
49+
echo "Unknown option: $1" >&2
50+
shift
51+
;;
52+
esac
53+
done
54+
55+
# Auto-detect if we need sudo (running as non-root)
56+
if [ -z "$SUDO" ] && [ "$(id -u)" -ne 0 ]; then
57+
SUDO="sudo"
58+
fi
59+
60+
echo "Configuration:"
61+
echo " Workspace root: $WORKSPACE_ROOT (informational only)"
62+
echo " Using sudo: $([ -n "$SUDO" ] && echo "yes" || echo "no")"
63+
echo " Install CLI: $INSTALL_CLI"
64+
echo " Build from source: $BUILD_FROM_SOURCE"
65+
echo ""
66+
67+
have_cmd() { command -v "$1" >/dev/null 2>&1; }
68+
69+
have_tree_sitter() {
70+
[ -f /usr/include/tree-sitter/api.h ] && return 0
71+
[ -f /usr/local/include/tree-sitter/api.h ] && return 0
72+
[ -f /usr/local/include/tree-sitter/lib/include/api.h ] && return 0
73+
ldconfig -p 2>/dev/null | grep -q libtree-sitter && return 0 || return 1
74+
}
75+
76+
install_tree_sitter_from_source() {
77+
echo "[ubuntu] Attempting to build and install tree-sitter from source..."
78+
tmpdir=$(mktemp -d /tmp/tree-sitter-src-XXXX)
79+
trap 'rm -rf "$tmpdir"' EXIT
80+
git clone --depth 1 https://github.com/tree-sitter/tree-sitter.git "$tmpdir" || return 1
81+
pushd "$tmpdir" >/dev/null || return 1
82+
if ! make; then
83+
echo "[ubuntu] ERROR: 'make' failed while building tree-sitter" >&2
84+
popd >/dev/null
85+
return 1
86+
fi
87+
88+
$SUDO mkdir -p /usr/local/include/tree-sitter
89+
$SUDO cp -r lib/include/* /usr/local/include/tree-sitter/ || true
90+
$SUDO cp -a lib/libtree-sitter.* /usr/local/lib/ 2>/dev/null || true
91+
if have_cmd ldconfig; then
92+
$SUDO ldconfig || true
93+
fi
94+
95+
popd >/dev/null
96+
echo "[ubuntu] tree-sitter built and installed to /usr/local (headers + libs)."
97+
return 0
98+
}
99+
100+
echo "Installing tree-sitter system library and dependencies..."
101+
$SUDO apt-get update -y
102+
# libtree-sitter-dev is optional when building from source via --build
103+
if ! $SUDO apt-get install -y \
104+
build-essential \
105+
pkg-config \
106+
$( [ "$BUILD_FROM_SOURCE" = false ] && echo "libtree-sitter-dev" ) \
107+
wget \
108+
gcc \
109+
g++ \
110+
make \
111+
zlib1g-dev \
112+
libssl-dev \
113+
libreadline-dev \
114+
libyaml-dev \
115+
libxml2-dev \
116+
libxslt1-dev \
117+
libcurl4-openssl-dev \
118+
software-properties-common \
119+
libffi-dev; then
120+
echo "ERROR: apt-get failed to install required packages."
121+
echo "Please check your network, package sources, and re-run this script."
122+
exit 1
123+
fi
124+
125+
# If the user requested a source-build, skip installing libtree-sitter-dev
126+
if [ "$BUILD_FROM_SOURCE" = true ]; then
127+
echo "[ubuntu] --build specified; skipping distro package 'libtree-sitter-dev' and building tree-sitter from source."
128+
fi
129+
130+
# Ensure tree-sitter is available; if not, attempt to build from source
131+
if ! have_tree_sitter; then
132+
if [ "$BUILD_FROM_SOURCE" = true ]; then
133+
echo "[ubuntu] tree-sitter not found in system paths; attempting to build from source as requested (--build)."
134+
if ! install_tree_sitter_from_source; then
135+
echo "[ubuntu] ERROR: Failed to provide tree-sitter runtime/library. Aborting." >&2
136+
exit 1
137+
fi
138+
else
139+
echo "[ubuntu] ERROR: tree-sitter runtime (headers/libs) not found."
140+
echo "Install the appropriate distro package (e.g., libtree-sitter-dev) or re-run this script with --build to compile from source."
141+
exit 1
142+
fi
143+
fi
144+
145+
# Install tree-sitter CLI via npm (optional)
146+
if [ "$INSTALL_CLI" = true ]; then
147+
echo "Installing tree-sitter-cli via npm..."
148+
$SUDO npm install -g tree-sitter-cli
149+
else
150+
echo "Skipping tree-sitter-cli installation (use --cli flag to install)"
151+
fi
152+
153+
# Install all tree-sitter grammars for integration testing
154+
GRAMMARS=("toml" "json" "jsonc" "bash")
155+
156+
TMPDIR=$(mktemp -d)
157+
trap "rm -rf $TMPDIR" EXIT
158+
159+
for grammar in "${GRAMMARS[@]}"; do
160+
echo "Building and installing tree-sitter-${grammar}..."
161+
cd "$TMPDIR"
162+
163+
if ! wget -q "https://github.com/tree-sitter-grammars/tree-sitter-${grammar}/archive/refs/heads/master.zip" -O "${grammar}.zip"; then
164+
echo "ERROR: Failed to download tree-sitter-${grammar}" >&2
165+
exit 1
166+
fi
167+
168+
if ! unzip -q "${grammar}.zip"; then
169+
echo "ERROR: Failed to unzip tree-sitter-${grammar}" >&2
170+
exit 1
171+
fi
172+
173+
cd "tree-sitter-${grammar}-master"
174+
175+
# Compile parser.c
176+
if ! gcc -fPIC -I./src -c src/parser.c -o parser.o; then
177+
echo "ERROR: Failed to compile parser.c for ${grammar}" >&2
178+
exit 1
179+
fi
180+
181+
# Check if scanner exists (not all grammars have scanners)
182+
if [ -f src/scanner.c ]; then
183+
if ! gcc -fPIC -I./src -c src/scanner.c -o scanner.o; then
184+
echo "ERROR: Failed to compile scanner.c for ${grammar}" >&2
185+
exit 1
186+
fi
187+
OBJECTS="parser.o scanner.o"
188+
else
189+
OBJECTS="parser.o"
190+
fi
191+
192+
# Link object files into shared library
193+
if ! gcc -shared -o "libtree-sitter-${grammar}.so" $OBJECTS; then
194+
echo "ERROR: Failed to link libtree-sitter-${grammar}.so" >&2
195+
exit 1
196+
fi
197+
198+
# Install to system
199+
if ! $SUDO cp "libtree-sitter-${grammar}.so" /usr/local/lib/; then
200+
echo "ERROR: Failed to copy libtree-sitter-${grammar}.so to /usr/local/lib/" >&2
201+
exit 1
202+
fi
203+
204+
echo " ✓ Installed tree-sitter-${grammar}"
205+
done
206+
207+
if ! $SUDO ldconfig; then
208+
echo "WARNING: ldconfig failed, libraries may not be immediately available" >&2
209+
fi
210+
211+
echo ""
212+
echo "tree-sitter setup complete!"
213+
echo ""
214+
echo "Detected library paths:"
215+
216+
# Detect and report tree-sitter runtime library location
217+
if [ -f /usr/lib/x86_64-linux-gnu/libtree-sitter.so.0 ]; then
218+
echo " TREE_SITTER_RUNTIME_LIB=/usr/lib/x86_64-linux-gnu/libtree-sitter.so.0"
219+
elif [ -f /usr/lib/x86_64-linux-gnu/libtree-sitter.so ]; then
220+
echo " TREE_SITTER_RUNTIME_LIB=/usr/lib/x86_64-linux-gnu/libtree-sitter.so"
221+
elif [ -f /usr/lib/libtree-sitter.so.0 ]; then
222+
echo " TREE_SITTER_RUNTIME_LIB=/usr/lib/libtree-sitter.so.0"
223+
elif [ -f /usr/lib/libtree-sitter.so ]; then
224+
echo " TREE_SITTER_RUNTIME_LIB=/usr/lib/libtree-sitter.so"
225+
else
226+
echo " WARNING: Could not find libtree-sitter runtime library!"
227+
fi
228+
229+
echo ""
230+
echo "Grammar libraries:"
231+
for grammar in "${GRAMMARS[@]}"; do
232+
echo " TREE_SITTER_${grammar^^}_PATH=/usr/local/lib/libtree-sitter-${grammar}.so"
233+
done
234+

.envrc

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,25 @@ export K_SOUP_COV_COMMAND_NAME="Test Coverage"
3333
# Available formats are html, xml, rcov, lcov, json, tty
3434

3535
export K_SOUP_COV_FORMATTERS="html,xml,rcov,lcov,json,tty"
36-
export K_SOUP_COV_MIN_BRANCH=86 # Means you want to enforce X% branch coverage
37-
export K_SOUP_COV_MIN_LINE=99 # Means you want to enforce X% line coverage
36+
export K_SOUP_COV_MIN_BRANCH=41 # Means you want to enforce X% branch coverage
37+
export K_SOUP_COV_MIN_LINE=88 # Means you want to enforce X% line coverage
3838
export K_SOUP_COV_MIN_HARD=true # Means you want the build to fail if the coverage thresholds are not met
3939
export K_SOUP_COV_MULTI_FORMATTERS=true
4040
export K_SOUP_COV_OPEN_BIN=false # Means don't try to open coverage results in browser
4141
export MAX_ROWS=1 # Setting for simplecov-console gem for tty output, limits to the worst N rows of bad coverage
4242
export KETTLE_TEST_SILENT=true
4343
export KETTLE_DEV_DEBUG=false
44+
export KETTLE_RB_DEV=false
4445

4546
# Internal Debugging Controls
4647

4748
export DEBUG=false # do not allow byebug statements (override in .env.local)
4849
export FLOSS_CFG_FUND_DEBUG=false # extra logging to help diagnose issues (override in .env.local)
4950
export FLOSS_CFG_FUND_LOGFILE=tmp/log/debug.log
5051

52+
# YARD - the yard-fence plugin is able to clean up the docs dir on each run, so stale docs don't linger
53+
export YARD_FENCE_CLEAN_DOCS=true
54+
5155
# Concurrently developing the rubocop-lts suite?
5256

5357
export RUBOCOP_LTS_LOCAL=false
@@ -57,6 +61,42 @@ export RUBOCOP_LTS_LOCAL=false
5761
export OPENCOLLECTIVE_HANDLE=kettle-rb
5862
export FUNDING_ORG=kettle-rb
5963

64+
# tree_haver dependencies (SONAME form)
65+
export TREE_SITTER_RUNTIME_LIB=/home/linuxbrew/.linuxbrew/Cellar/tree-sitter/0.26.3/lib/libtree-sitter.so
66+
# Run vendor/setup-java-tree-sitter.sh to download JARs
67+
export TREE_SITTER_JAVA_JARS_DIR=/home/pboling/src/kettle-rb/ast-merge/vendor/tree_haver/vendor/jars
68+
# JVM options for java-tree-sitter:
69+
# - --enable-native-access: Required for Java Foreign Function API
70+
# - -Djava.library.path: Path to libtree-sitter.so for JNI loading
71+
export JAVA_OPTS="--enable-native-access=ALL-UNNAMED -Djava.library.path=/home/linuxbrew/.linuxbrew/Cellar/tree-sitter/0.26.3/lib"
72+
export JRUBY_OPTS="-J--enable-native-access=ALL-UNNAMED -J-Djava.library.path=/home/linuxbrew/.linuxbrew/Cellar/tree-sitter/0.26.3/lib"
73+
export CLASSPATH="${TREE_SITTER_JAVA_JARS_DIR}/jtreesitter-0.26.0.jar${CLASSPATH:+:$CLASSPATH}"
74+
# If Ruby/JRuby cannot find libraries at runtime, you may need to export:
75+
# LD_LIBRARY_PATH is needed for java-tree-sitter to find libtree-sitter.so at runtime
76+
# export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib64:/usr/lib
77+
export LD_LIBRARY_PATH="/home/linuxbrew/.linuxbrew/Cellar/tree-sitter/0.26.3/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
78+
79+
# Example language library path:
80+
# Luarocks grammars were built with treesitter < 0.24, which has a different ABI than later versions.
81+
# export TREE_SITTER_TOML_PATH=/home/pboling/.local/share/mise/installs/lua/5.4.8/luarocks/lib/luarocks/rocks-5.4/tree-sitter-toml/0.0.31-1/parser/toml.so
82+
# export TREE_SITTER_JSON_PATH=/home/pboling/.local/share/mise/installs/lua/5.4.8/luarocks/lib/luarocks/rocks-5.4/tree-sitter-json/0.0.29-1/parser/json.so
83+
# export TREE_SITTER_JSONC_PATH=/home/pboling/.local/share/mise/installs/lua/5.4.8/luarocks/lib/luarocks/rocks-5.4/tree-sitter-jsonc/0.0.29-1/parser/jsonc.so
84+
# Luarocks version (incompatible with MRI backend):
85+
# export TREE_SITTER_BASH_PATH=/home/pboling/.local/share/mise/installs/lua/5.4.8/luarocks/lib/luarocks/rocks-5.4/tree-sitter-bash/0.0.49-1/parser/bash.so
86+
# npm version (N-API, so WILL NOT WORK with ruby_tree_sitter):
87+
# export TREE_SITTER_BASH_PATH=/var/home/pboling/.local/share/mise/installs/node/23.11.0/lib/node_modules/tree-sitter-bash/prebuilds/linux-x64/tree-sitter-bash.node
88+
# Compiled from source (compatible with ruby_tree_sitter, by tree_haver's `bin/build-grammar <grammar-name>`)
89+
export TREE_SITTER_BASH_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-bash.so"
90+
export TREE_SITTER_CSS_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-css.so"
91+
export TREE_SITTER_JAVASCRIPT_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-javascript.so"
92+
export TREE_SITTER_JSON_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-json.so"
93+
export TREE_SITTER_JSONC_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-jsonc.so"
94+
export TREE_SITTER_PYTHON_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-python.so"
95+
export TREE_SITTER_RBS_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-rbs.so"
96+
export TREE_SITTER_RUBY_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-ruby.so"
97+
export TREE_SITTER_TOML_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-toml.so"
98+
export TREE_SITTER_YAML_PATH="/home/pboling/.local/lib/tree-sitter/libtree-sitter-yaml.so"
99+
60100
# .env would override anything in this file, if `dotenv` is uncommented below.
61101

62102
# .env is a DOCKER standard, and if we use it, it would be in deployed, or DOCKER, environments,

.gemrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
gem: --no-document

0 commit comments

Comments
 (0)