diff --git a/.ci/force_json_020.jl b/.ci/force_json_020.jl new file mode 100644 index 00000000..4fd33a4c --- /dev/null +++ b/.ci/force_json_020.jl @@ -0,0 +1,32 @@ +# Rewrites the JSON entry in the [compat] section of Project.toml to "0.20" so +# that every subsequent resolve can only pick JSON 0.20.x — the last JSON +# version without non-stdlib dependencies, which is what the VS Code extension +# uses on every Julia version. +# +# This must run on Julia 1.0 (no TOML stdlib), so the file is edited line by +# line, tracking the current section: [deps] also has a `JSON = ""` line +# that must be left alone. + +function force_json_020() + lines = readlines("Project.toml") + section = "" + replaced = false + for i in eachindex(lines) + stripped = strip(lines[i]) + if startswith(stripped, "[") + section = stripped + elseif section == "[compat]" && occursin(r"^JSON\s*=", stripped) + lines[i] = "JSON = \"0.20\"" + replaced = true + end + end + replaced || error("No JSON entry found in the [compat] section of Project.toml") + open("Project.toml", "w") do io + for line in lines + println(io, line) + end + end + println("Restricted Project.toml compat to JSON = \"0.20\"") +end + +force_json_020() diff --git a/.ci/verify_json_020.jl b/.ci/verify_json_020.jl new file mode 100644 index 00000000..67eaef78 --- /dev/null +++ b/.ci/verify_json_020.jl @@ -0,0 +1,31 @@ +# Fails loudly unless the resolved Manifest.toml has JSON at version 0.20.x, +# so a silent fallback to a newer JSON cannot go unnoticed after +# force_json_020.jl tightened the compat bound. +# +# Must run on Julia 1.0 (no TOML stdlib): scans the manifest line by line for +# the JSON stanza, handling both manifest formats — `[[JSON]]` (old) and +# `[[deps.JSON]]` (Julia >= 1.6.2). + +function verify_json_020() + in_json_stanza = false + for line in readlines("Manifest.toml") + stripped = strip(line) + if startswith(stripped, "[") + in_json_stanza = stripped == "[[JSON]]" || stripped == "[[deps.JSON]]" + elseif in_json_stanza + m = match(r"^version\s*=\s*\"(.*)\"", stripped) + if m !== nothing + version = m.captures[1] + if startswith(version, "0.20.") + println("JSON resolved to version ", version) + return + else + error("JSON resolved to version $version, expected 0.20.x") + end + end + end + end + error("No JSON version found in Manifest.toml") +end + +verify_json_020() diff --git a/.github/workflows/juliaci-oldjson.yml b/.github/workflows/juliaci-oldjson.yml new file mode 100644 index 00000000..01e06d41 --- /dev/null +++ b/.github/workflows/juliaci-oldjson.yml @@ -0,0 +1,83 @@ +name: Julia CI (JSON 0.20) + +# Tests JSONRPC against JSON 0.20 on every supported Julia version. The VS Code +# extension uses JSON 0.20 on all Julia versions because it is the last JSON +# version without non-stdlib dependencies, so this combination has to keep +# working even though a plain resolve would pick JSON 0.21 (Julia <= 1.8) or +# JSON 1.x (Julia >= 1.9). This is deliberately a standalone workflow built +# from the individual julia-actions rather than a second invocation of the +# testitem-workflow template, which would drag along duplicate lint, docs and +# TagBot jobs. + +on: + push: {branches: [main,master]} + pull_request: {types: [opened,synchronize,reopened,ready_for_review,converted_to_draft]} + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} + cancel-in-progress: true + +jobs: + compute-test-matrix: + runs-on: ubuntu-latest + outputs: + test-matrix: ${{ steps.matrix.outputs.test-matrix }} + steps: + - uses: actions/checkout@v7 + - uses: julia-actions/julia-compute-test-matrix@v2 + id: matrix + with: + include-release-versions: true + include-lts-versions: true + include-rc-versions: true + include-all-compatible-minor-versions: true + + test: + needs: compute-test-matrix + strategy: + fail-fast: false + matrix: + include: ${{ fromJson(needs.compute-test-matrix.outputs.test-matrix) }} + runs-on: ${{ matrix.os }} + continue-on-error: ${{ matrix.allow-failure }} + steps: + - uses: actions/checkout@v7 + - uses: julia-actions/install-juliaup@v3 + with: + channel: ${{ matrix.juliaup-channel }} + - uses: julia-actions/cache@v3 + # Same bootstrap as the testitem-workflow template: `julia-buildpkg` only + # installs a registry from Julia 1.5 on, and Pkg before that does not + # clone one on demand either. + - name: Install the General registry on Julia < 1.5 + shell: bash + run: | + julia -e ' + VERSION < v"1.5" || exit() + general = joinpath(DEPOT_PATH[1], "registries", "General") + isfile(joinpath(general, "Registry.toml")) && exit() + if ispath(general) + println("Registry at $general is unusable, replacing it") + # git marks its object files read-only, which blocks the delete on Windows + for (root, dirs, files) in walkdir(general), f in files + try chmod(joinpath(root, f), 0o777) catch end + end + rm(general, recursive=true) + end + mkpath(dirname(general)) + run(`git clone --quiet --depth=1 https://github.com/JuliaRegistries/General.git $general`) + ' + # Rewriting the compat entry before buildpkg means the ordinary + # instantiate resolves JSON 0.20.x, and any later re-resolution is + # equally constrained. + - name: Restrict JSON compat to 0.20 + shell: bash + run: julia .ci/force_json_020.jl + - uses: julia-actions/julia-buildpkg@v1 + - name: Verify JSON 0.20 was resolved + shell: bash + run: julia .ci/verify_json_020.jl + - uses: julia-actions/julia-run-testitems@v2 + with: + juliaup-channel: ${{ matrix.juliaup-channel }} + profile-name: ${{ format('Julia {0}:{1} (JSON 0.20)', matrix.juliaup-channel, matrix.os) }} diff --git a/.github/workflows/juliaci.yml b/.github/workflows/juliaci.yml index 79056ef5..888a57b3 100644 --- a/.github/workflows/juliaci.yml +++ b/.github/workflows/juliaci.yml @@ -17,21 +17,3 @@ jobs: permissions: write-all secrets: codecov_token: ${{ secrets.CODECOV_TOKEN }} - - json-compat: - name: JSON ${{ matrix.json-version }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - json-version: ["0.21", "1.7"] - steps: - - uses: actions/checkout@v4 - - uses: julia-actions/setup-julia@v2 - with: - version: "1" - - uses: julia-actions/cache@v2 - - name: Install and verify JSON version - run: | - julia --project=. -e 'using Pkg; Pkg.add(PackageSpec(name="JSON", version="${{ matrix.json-version }}")); using JSON; @assert startswith(string(pkgversion(JSON)), "${{ matrix.json-version }}."); Pkg.status()' - - uses: julia-actions/julia-runtest@v1