Skip to content
Merged
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
22 changes: 11 additions & 11 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,13 @@ jobs:
fi
-
# Both Linux targets build on native matching runners. `lc version`
# boots the application and performs a hidden Marcli render, forcing
# mdex_native and its NIF to load before the command can exit 0. No API
# key or network is needed. macOS/Windows runtime smoke tests remain
# out of scope because their hosted runners are not all native to the
# configured Burrito targets.
# boots the application and performs a hidden syntax-highlighted Marcli
# render, forcing mdex_native, its NIF, Makeup, and the Elixir lexer to
# load before the command can exit 0. No API key or network is needed.
# macOS/Windows runtime smoke tests remain out of scope because their
# hosted runners are not all native to the configured Burrito targets.
if: startsWith(matrix.target, 'linux_')
name: Smoke-test the ${{ matrix.target }} binary and Markdown NIF
name: Smoke-test the ${{ matrix.target }} binary and Markdown runtime
timeout-minutes: 1
run: ./burrito_out/lc_${{ matrix.target }} version
-
Expand Down Expand Up @@ -376,16 +376,16 @@ jobs:
run: ./ci/build_image.sh "${{ needs.burrito-package.outputs.tag_name }}"
-
# Verify the musl NIF actually loads on Alpine before publishing.
# `lc version` boots the OTP app and performs a hidden Markdown render,
# forcing mdex_native's NIF and its bundled libgcc runtime to load.
# It then prints the version and exits 0; no API key or network is
# needed. ci/build_image.sh prefers
# `lc version` boots the OTP app and performs a hidden syntax-highlighted
# Markdown render, forcing mdex_native's NIF, its bundled libgcc runtime,
# Makeup, and the Elixir lexer to load. It then prints the version and
# exits 0; no API key or network is needed. ci/build_image.sh prefers
# Podman, so the image lives in Podman's local storage; we run it
# directly rather than loading a tarball. LINEAR_CLI_DAEMON is
# overridden to false (the image bakes in true so the default CMD
# starts the daemon; without this override the app ignores `version`
# and stays alive as a daemon, timing out the step). See EXT-7.
name: Smoke-test the container image boots and NIFs load on Alpine/musl
name: Smoke-test the container image Markdown runtime on Alpine/musl
timeout-minutes: 1
run: |
podman run --rm -e LINEAR_CLI_DAEMON=false "linear-cli:${{ needs.burrito-package.outputs.tag_name }}" lc version
Expand Down
13 changes: 10 additions & 3 deletions app/lib/linear_cli/cli/commands.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ defmodule LinearCli.CLI.Commands do
Ported from commands/version.rb, extended to respect the global
`--output json` option like every other command does - previously
ignored it and always printed plain text. The hidden Markdown render makes
this command a complete release smoke test for mdex_native's NIF as well as
the application boot path.
this command a complete release smoke test for mdex_native's NIF, Marcli's
syntax-highlighting lexer, and the application boot path.
"""
def version(%{options: options}) do
verify_markdown_runtime!()
Expand All @@ -36,7 +36,14 @@ defmodule LinearCli.CLI.Commands do
end

defp verify_markdown_runtime! do
_rendered = Marcli.render("runtime check", escape_sequences: false)
theme = Marcli.Theme.default()
rendered = Marcli.render("```elixir\ndef smoke, do: :ok\n```")
highlighted_keyword = theme.syntax.keyword_declaration <> "def" <> theme.reset

unless String.contains?(rendered, highlighted_keyword) do
raise "Markdown syntax-highlighting runtime is unavailable"
end

:ok
end

Expand Down
1 change: 1 addition & 0 deletions app/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ defmodule LinearCli.MixProject do
defp deps do
[
{:marcli, "~> 0.3"},
{:makeup_elixir, "~> 1.0"},
{:owl, "~> 0.13"},
{:optimus, "~> 0.6"},
{:req, "~> 0.7"},
Expand Down
2 changes: 2 additions & 0 deletions app/mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
"igniter": {:hex, :igniter, "0.8.3", "9de74d3885efae43b0b58dc6f7b816963c4bbd391e6b6fe6922ee21c4e384c76", [:mix], [{:ex_ast, "~> 0.5", [hex: :ex_ast, repo: "hexpm", optional: false]}, {:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4.5", [hex: :jason, repo: "hexpm", optional: false]}, {:owl, "~> 0.11", [hex: :owl, repo: "hexpm", optional: false]}, {:phx_new, "~> 1.7", [hex: :phx_new, repo: "hexpm", optional: true]}, {:req, "~> 0.5", [hex: :req, repo: "hexpm", optional: false]}, {:rewrite, ">= 1.1.1 and < 2.0.0-0", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "afc5e3848d885e680da5c3b65e5e7717555a08cd12305190ff2be76427af39ff"},
"iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"},
"jason": {:hex, :jason, "1.4.5", "2e3a008590b0b8d7388c20293e9dcc9cf3e5d642fd2a114e4cbbb52e595d940a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "b0c823996102bcd0239b3c2444eb00409b72f6a140c1950bc8b457d836b30684"},
"makeup": {:hex, :makeup, "1.2.2", "882d46dc0905e9ff7abf2aab61a7e6b3dcc555533977d8a23b06019e6c89ac94", [:mix], [{:nimble_parsec, "~> 1.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "9a1a24e5b343b8ae16abea0822c10a6f75da27af7fa802ada5251f7579bfccfa"},
"makeup_elixir": {:hex, :makeup_elixir, "1.0.1", "e928a4f984e795e41e3abd27bfc09f51db16ab8ba1aebdba2b3a575437efafc2", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "7284900d412a3e5cfd97fdaed4f5ed389b8f2b4cb49efc0eb3bd10e2febf9507"},
"marcli": {:hex, :marcli, "0.3.1", "183d2c674e416cdd90a5b395d60d573ad5d4381ec18239de2b2cfa249d926d7c", [:mix], [{:color, "~> 0.3", [hex: :color, repo: "hexpm", optional: true]}, {:makeup, "~> 1.2", [hex: :makeup, repo: "hexpm", optional: true]}, {:mdex, "~> 0.11", [hex: :mdex, repo: "hexpm", optional: false]}], "hexpm", "731383f9b9bdfd13affe2d43a3cef441440c4a9182cb59724478e51b85e2c7d4"},
"mdex": {:hex, :mdex, "0.13.5", "c1c94d230ccaab01ad0c68090d3b31613c10ece1844f32b55895da4ce0c63029", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:lumis, "~> 0.1", [hex: :lumis, repo: "hexpm", optional: true]}, {:mdex_native, ">= 0.2.6", [hex: :mdex_native, repo: "hexpm", optional: false]}, {:nimble_options, "~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20.0 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}], "hexpm", "c57409fb6b34fbc58fbce0a6da670c9a4b5a2e94f86abdc56e9e213ed74620f2"},
"mdex_native": {:hex, :mdex_native, "0.2.7", "46203ee9c4fe2c94feef26e4d976235ad022b4770d3d307fa6b445d293b2571f", [:mix], [{:rustler, "~> 0.32", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.8", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "05efa68775644ef6be6109f76c1f5f8778ff7e7ed9fe4a03541758158172bc77"},
Expand Down
32 changes: 32 additions & 0 deletions app/test/linear_cli/cli/display_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule LinearCli.CLI.DisplayTest do
use ExUnit.Case, async: true

import ExUnit.CaptureIO

alias LinearCli.CLI.Display
alias LinearCli.Linear.Issue

test "full issue output syntax-highlights fenced Elixir code" do
issue = %Issue{
id: "issue-1",
identifier: "EXT-1",
title: "Highlight markdown",
description: """
```elixir
defmodule Example do
def answer, do: 42
end
```
""",
comments: []
}

output = capture_io(fn -> Display.show(issue, %{full: true}) end)
theme = Marcli.Theme.default()

assert output =~ theme.syntax.keyword_declaration <> "defmodule" <> theme.reset
assert output =~ theme.syntax.name_class <> "Example" <> theme.reset
assert output =~ theme.syntax.number <> "42" <> theme.reset
refute output =~ theme.code_text <> "defmodule"
end
end
Loading