Skip to content
Open
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
68 changes: 61 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up JDK 17
- name: Set up JDK 25
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
java-version: '17'
java-version: '25'
cache: maven

- name: Run tests
Expand All @@ -40,17 +40,18 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up JDK 17
- name: Set up JDK 25
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
java-version: '17'
java-version: '25'
cache: maven

- name: Package server JAR
run: mvn --batch-mode -DskipTests package

- name: Set up JDK for Gradle
# Gradle 9.0 does not run on Java 25 yet; the plugin itself targets the IDE's 17 toolchain.
- name: Set up JDK 17 for Gradle
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
Expand Down Expand Up @@ -88,11 +89,11 @@ jobs:
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up JDK 17
- name: Set up JDK 25
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
java-version: '17'
java-version: '25'
cache: maven

- name: Package server JAR
Expand All @@ -114,3 +115,56 @@ jobs:
with:
name: vscode-extension-${{ matrix.target }}
path: vscode-extension/*.vsix

native-binary:
name: Build native binary (${{ matrix.target }})
runs-on: ${{ matrix.os }}
needs: server
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: linux-x64
- os: ubuntu-24.04-arm
target: linux-arm64
- os: windows-latest
target: win32-x64
- os: macos-15-intel
target: darwin-x64
- os: macos-latest
target: darwin-arm64
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Set up GraalVM for JDK 25
uses: graalvm/setup-graalvm@27b360dbb857524eaf0b4c4cef364d38e5b4f173 # v1.6.7
with:
distribution: graalvm-community
java-version: '25'
cache: maven
native-image-job-reports: 'true'

- name: Build native binary
run: mvn --batch-mode -DskipTests -Pnative package

- name: Smoke test the binary against the demo project
shell: bash
run: ./.github/workflows/native_smoke_test.sh doc/demo/example target/openfasttrace-language-server

- name: Name the binary after version and platform
shell: bash
run: |
version=$(sed -n 's/.*<version>\(.*\)<\/version>.*/\1/p' pom.xml | head -n 1)
extension=""
if [[ "${{ runner.os }}" == "Windows" ]]; then extension=".exe"; fi
mkdir -p target/native
mv "target/openfasttrace-language-server${extension}" \
"target/native/openfasttrace-language-server-${version}-${{ matrix.target }}${extension}"
ls -l target/native

- name: Upload native binary
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: native-binary-${{ matrix.target }}
path: target/native/*
27 changes: 25 additions & 2 deletions .github/workflows/github_release.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,16 @@ if [[ ${#vscode_extensions[@]} -eq 0 ]]; then
exit 1
fi

echo "Calculate sha256sum for plugin archive, server JAR and VS Code extension"
# One native binary per platform, for editors without a Java runtime (ADR 0016).
mapfile -t native_binaries < <(find "$base_dir/target/native" -maxdepth 1 -type f \
-name "openfasttrace-language-server-${project_version}-*" ! -name '*.sha256' 2>/dev/null | sort)
readonly native_binaries
if [[ ${#native_binaries[@]} -eq 0 ]]; then
echo "Could not find any native binary in $base_dir/target/native" >&2
exit 1
fi

echo "Calculate sha256sum for plugin archive, server JAR, VS Code extensions and native binaries"

# checksum for plugin
file_dir="$(dirname "$artifact_path")"
Expand Down Expand Up @@ -99,6 +108,18 @@ for extension in "${vscode_extensions[@]}"; do
done
readonly vscode_upload_files

# checksums for every native binary
native_upload_files=()
for binary in "${native_binaries[@]}"; do
native_dir="$(dirname "$binary")"
native_name="$(basename "$binary")"
cd "$native_dir"
sha256sum "$native_name" > "${native_name}.sha256"
cd "$base_dir"
native_upload_files+=("$binary" "$native_dir/${native_name}.sha256")
done
readonly native_upload_files

readonly title="Release $project_version"
readonly tag="$project_version"
echo "Creating release:"
Expand All @@ -111,10 +132,12 @@ echo "Server JAR : $server_jar"
echo "Server sha256: $checksum_server_path"
echo "VS Code ext. : ${#vscode_extensions[@]} package(s)"
printf ' %s\n' "${vscode_extensions[@]}"
echo "Native binary: ${#native_binaries[@]} file(s)"
printf ' %s\n' "${native_binaries[@]}"

release_url=$(gh release create --latest --title "$title" --notes-file "$changes_file" --target main "$tag" \
"$artifact_path" "$checksum_plugin_path" "$server_jar" "$checksum_server_path" \
"${vscode_upload_files[@]}")
"${vscode_upload_files[@]}" "${native_upload_files[@]}")
readonly release_url
echo "Release URL: $release_url"

Expand Down
102 changes: 102 additions & 0 deletions .github/workflows/native_smoke_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/env bash

# Drives one LSP session against a server over stdio and checks that the server answers.
#
# Usage: native_smoke_test.sh <workspace directory> <server command...>
#
# The session opens the workspace, waits for the trace diagnostics, asks for all workspace
# symbols, then shuts the server down. It fails when any answer is missing or the server does
# not exit. Meant for the native binary, where a missing reflection registration only shows
# at run time, but works for `java -jar` as well.

set -o errexit
set -o nounset
set -o pipefail

if [[ $# -lt 2 ]]; then
echo "Usage: $0 <workspace directory> <server command...>" >&2
exit 2
fi

workspace="$1"
shift

case "$(uname -s)" in
MINGW*|MSYS*|CYGWIN*) root_uri="file:///$(cd "$workspace" && pwd -W)" ;;
*) root_uri="file://$(cd "$workspace" && pwd -P)" ;;
esac

message() {
local body="$1"
# The bodies are ASCII, so the character count equals the byte count.
printf 'Content-Length: %d\r\n\r\n%s' "${#body}" "$body"
}

session() {
message '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"processId":null,"rootUri":"'"$root_uri"'","capabilities":{},"workspaceFolders":[{"uri":"'"$root_uri"'","name":"workspace"}]}}'
message '{"jsonrpc":"2.0","method":"initialized","params":{}}'
sleep 5
message '{"jsonrpc":"2.0","id":2,"method":"workspace/symbol","params":{"query":""}}'
sleep 2
message '{"jsonrpc":"2.0","id":3,"method":"shutdown"}'
sleep 1
message '{"jsonrpc":"2.0","method":"exit"}'
}

stdout_file="$(mktemp)"
stderr_file="$(mktemp)"
trap 'rm -f "$stdout_file" "$stderr_file"' EXIT

echo "Starting: $*"
echo "Workspace: $root_uri"
session | "$@" >"$stdout_file" 2>"$stderr_file" &
server_pid=$!

for _ in $(seq 1 60); do
if ! kill -0 "$server_pid" 2>/dev/null; then
break
fi
sleep 1
done

if kill -0 "$server_pid" 2>/dev/null; then
echo "Server did not exit within 60 seconds" >&2
kill "$server_pid" 2>/dev/null || true
cat "$stderr_file" >&2
exit 1
fi

exit_code=0
wait "$server_pid" || exit_code=$?

failed=0
check() {
local description="$1" pattern="$2"
if grep -q -- "$pattern" "$stdout_file"; then
echo "ok $description"
else
echo "FAIL $description (no match for '$pattern')" >&2
failed=1
fi
}

check "initialize answered with capabilities" '"id":1,"result":{"capabilities"'
check "trace diagnostics published for the workspace" '"method":"textDocument/publishDiagnostics"'
check "workspace symbols returned" '"id":2,"result":\[{'
check "shutdown answered" '"id":3,"result":null'

if [[ $exit_code -ne 0 ]]; then
echo "FAIL server exited with code $exit_code" >&2
failed=1
fi

if [[ $failed -ne 0 ]]; then
echo "--- server stderr:" >&2
cat "$stderr_file" >&2
echo "--- server stdout (first 2000 bytes):" >&2
head -c 2000 "$stdout_file" >&2
echo >&2
exit 1
fi

echo "Smoke test passed"
80 changes: 72 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,11 @@ jobs:
script: |
core.setFailed('This workflow must run on main. Current ref: ${{ github.ref }}')

- name: Set up JDK 17 for Maven
- name: Set up JDK 25 for Maven
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
java-version: '17'
java-version: '25'
cache: maven

- name: Build standalone server JAR
Expand All @@ -67,9 +67,67 @@ jobs:
name: vscode-extension-${{ matrix.target }}
path: vscode-extension/*.vsix

native-binaries:
name: Build native binary (${{ matrix.target }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
target: linux-x64
- os: ubuntu-24.04-arm
target: linux-arm64
- os: windows-latest
target: win32-x64
- os: macos-15-intel
target: darwin-x64
- os: macos-latest
target: darwin-arm64
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Fail if not running on main branch
if: ${{ github.ref != 'refs/heads/main' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
core.setFailed('This workflow must run on main. Current ref: ${{ github.ref }}')

- name: Set up GraalVM for JDK 25
uses: graalvm/setup-graalvm@27b360dbb857524eaf0b4c4cef364d38e5b4f173 # v1.6.7
with:
distribution: graalvm-community
java-version: '25'
cache: maven

- name: Build native binary
run: mvn --batch-mode -DskipTests -Pnative package

- name: Smoke test the binary against the demo project
shell: bash
run: ./.github/workflows/native_smoke_test.sh doc/demo/example target/openfasttrace-language-server

- name: Name the binary after version and platform
shell: bash
run: |
version=$(sed -n 's/.*<version>\(.*\)<\/version>.*/\1/p' pom.xml | head -n 1)
extension=""
if [[ "${{ runner.os }}" == "Windows" ]]; then extension=".exe"; fi
mkdir -p target/native
mv "target/openfasttrace-language-server${extension}" \
"target/native/openfasttrace-language-server-${version}-${{ matrix.target }}${extension}"

- name: Upload native binary
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: native-binary-${{ matrix.target }}
path: target/native/*

release:
runs-on: ubuntu-latest
needs: vscode-packages
needs: [vscode-packages, native-binaries]
defaults:
run:
shell: bash
Expand All @@ -87,16 +145,17 @@ jobs:
script: |
core.setFailed('This workflow must run on main. Current ref: ${{ github.ref }}')

- name: Set up JDK 17 for Maven
- name: Set up JDK 25 for Maven
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
distribution: temurin
java-version: '17'
java-version: '25'
cache: maven

- name: Build standalone server JAR
run: mvn --batch-mode -DskipTests package

# Gradle 9.0 does not run on Java 25 yet; the plugin itself targets the IDE's 17 toolchain.
- name: Set up JDK 17 for Gradle
uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # v6.0.1
with:
Expand All @@ -115,8 +174,15 @@ jobs:
path: vscode-extension
merge-multiple: true

- name: Download native binaries
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
pattern: native-binary-*
path: target/native
merge-multiple: true

- name: Create GitHub release
run: bash ./.github/workflows/github_release.sh
run: ./.github/workflows/github_release.sh
env:
GH_TOKEN: ${{ github.token }}

Expand All @@ -134,5 +200,3 @@ jobs:
echo "Publishing $package"
npx --yes ovsx publish "$package"
done


Loading
Loading