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
4 changes: 0 additions & 4 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,3 @@
# See: https://github.com/actions/runner/issues/4134
# https://github.com/orgs/community/discussions/180160
package-lock.json -text

# Hide our tests from language detection so GitHub correctly detects
# Topiary as a Rust project
topiary-cli/tests/samples/** linguist-vendored
24 changes: 24 additions & 0 deletions .github/actions/nix-build/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Nix tooling and build cache

inputs:
nix_path:
description: NIX_PATH environment
required: true

auth_token:
description: Cachix authentication token
required: true

runs:
using: composite
steps:
- name: Install Nix
uses: cachix/install-nix-action@v31
with:
nix_path: "${{ inputs.nix_path }}"

- name: Set up Nix cache
uses: cachix/cachix-action@v16
with:
name: tweag-topiary
authToken: "${{ inputs.auth_token }}"
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: CI

on:
push:
branches: trunk

pull_request:
branches: trunk

jobs:

nix-flake-check:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up build tooling
uses: ./.github/actions/nix-build
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
auth_token: "${{ secrets.CACHIX_TWEAG_TOPIARY_AUTH_TOKEN }}"

- name: Lint, format check and test
env:
# Disable Nix garbage collection
GC_DONT_GC: 1
run: nix -L flake check
195 changes: 195 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
name: Release

# NOTE In principle, the playground and language assets could be cached.
# However, releases will presumably be so infrequent that cached items
# will expire... So it's not worth the trouble.

permissions:
contents: write

on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'

env:
# FIXME The Topiary Playground and the grammar WASM assets are built
# with Tree-sitter 0.22.6. However, for some reason, the frontend does
# not work with this version of the Tree-sitter runtime and we have to
# explicitly use v0.21
TREE_SITTER_VERSION: 0.21.0
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

huh, that's interesting

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd guess a breaking change in the API, but it was easier to roll it back to 0.21 than debug 😅


jobs:

# Build Playground WASM assets
build-playground-wasm:

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up build tooling
uses: ./.github/actions/nix-build
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
auth_token: "${{ secrets.CACHIX_TWEAG_TOPIARY_AUTH_TOKEN }}"

- name: Build WASM assets
run: nix build

- name: Upload build artefacts
uses: actions/upload-artifact@v6
with:
name: playground-wasm
path: result/**


# Build supported languages grammar WASM, query and example assets
build-language-assets:

runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v6
with:
path: playground

- name: Get Topiary version
id: get-version
working-directory: ./playground
run: |
cargo metadata --format-version 1 --locked \
| jq -r '
.packages[]
| select(.name == "topiary-core")
| "topiary=\(.version)"
' \
| tee -a $GITHUB_OUTPUT

- name: Checkout Topiary
uses: actions/checkout@v6
with:
repository: topiary/topiary
ref: "v${{ steps.get-version.outputs.topiary }}"
path: topiary

- name: Set up build tooling
uses: ./playground/.github/actions/nix-build
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
auth_token: "${{ secrets.CACHIX_TWEAG_TOPIARY_AUTH_TOKEN }}"

- name: Build supported language grammar assets
run: |
mkdir build
cd build

nix run ../playground#build-wasm-grammars -- ../topiary/languages.ncl
nix run ../playground#build-languages-export -- ../topiary

- name: Upload build artefacts
uses: actions/upload-artifact@v6
with:
name: language-assets
path: build/*


# Copy all the required assets and build the playground's assets, then
# cut a GitHub release from the assets
build-playground-assets:

runs-on: ubuntu-latest
needs:
- build-playground-wasm
- build-language-assets

env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up asset directories
run: |
mkdir --parents \
web-playground/public/scripts \
web-playground/src/samples \
web-playground/src/wasm-app \

- name: Install Playground WASM
uses: actions/download-artifact@v7
with:
name: playground-wasm
path: ./web-playground/src/wasm-app

- name: Install Language assets
uses: actions/download-artifact@v7
with:
name: language-assets
path: ./web-playground/public/scripts

- name: Install Tree-sitter runtime
working-directory: ./web-playground/public/scripts
run: |
gh release download \
"v${TREE_SITTER_VERSION}" \
--repo tree-sitter/tree-sitter \
--pattern "tree-sitter.js" \
--pattern "tree-sitter.wasm" \

# NOTE There are end-to-end tests for the web playground. Because
# of the playground's development status, we don't currently
# bother running them, to speed up the CI. The original
# implementation did this, so it shouldn't be too difficult to
# reinstate...
#
# ```yaml
# - name: Test playground
# run: |
# npm install --prefix web-playground
# npm run dev --prefix web-playground &
#
# # Loop until there's a response
# while [[ "$(curl --silent --output /dev/null --write-out "%{http_code}" http://localhost:5173/playground)" != "200" ]]; do
# sleep 2
# done
#
# npm run e2e --prefix web-playground
# ```

- name: Build Playground static assets
run: |
# Move language exports to the right place
mv web-playground/public/scripts/languages_export.ts \
web-playground/src/samples/

# Build website assets
npm install --prefix web-playground
npm run build --prefix web-playground

# Package release
mkdir --parents htdocs/playground
cp --recursive web-playground/dist/. htdocs/playground
tar czf playground-htdocs.tar.gz htdocs

- name: Create GitHub Release
run: |
gh release create \
"${{ github.ref_name }}" \
--target "${{ github.sha }}" \
--generate-notes \
playground-htdocs.tar.gz

# TODO: Uncomment this when topiary/website and the PAT exist
# - name: Trigger website build
# env:
# # TODO Create a PAT with repo scope
# GH_TOKEN: ${{ secrets.DISPATCH_PAT }}
# run: |
# gh api \
# repos/topiary/website/dispatches \
# -f event_type='dependency-update' \
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ target
*.profraw
/.vscode
.envrc
*.wasm
languages_export.ts
112 changes: 112 additions & 0 deletions bin/build-languages-export.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#!/usr/bin/env bash

set -euo pipefail

if [[ -t 1 ]]; then
GREEN="$(tput setaf 2)"
ORANGE="$(tput setaf 3)"
RESET="$(tput sgr0)"
else
GREEN=""
ORANGE=""
RESET=""
fi
readonly ORANGE GREEN RESET

stderr() {
local colour="$1"
shift

printf "%s%s%s\n" "${colour}" "$*" "${RESET}" >&2
}

usage() {
cat <<-EOF
usage: $(basename "$0") TOPIARY_REPO

Build the languages export per the Topiary repository specified by
TOPIARY_REPO.
EOF

exit 1
}

get-language-info() {
# Read the supported language assets from the Topiary repository and
# stream out a tab-delimited list of language, query file and example
# input file
local repo="$1"
local language
local query
local example

for query in "${repo}/topiary-queries/queries/"*.scm; do
language="$(basename --suffix ".scm" "${query}")"

# ocaml_interface is an annoying special case
if [[ "${language}" = "ocaml_interface" ]]; then
language="ocaml-interface"
fi

example="$(find "${repo}/topiary-cli/tests/samples/input" -name "${language}.*")"

printf "%s\t%s\t%s\n" "${language}" "${query}" "${example}"
done
}

to-js-string() {
sed '
# Escape the escape character (must be done first)
s/\\/\\\\/g;

# Backticks are delimiters for template literals in JavaScript
s/`/\\`/g;

# Escape braced template literals
s/${/\\${/g
'
}

export-language() {
local language="$1"
local query="$2"
local example="$3"

stderr "${ORANGE}" "${language}: Exporting query and example"

cat <<-TYPESCRIPT
"${language}": {
"query": \`$(to-js-string < "${query}")\`,
"input": \`$(to-js-string < "${example}")\`,
},
TYPESCRIPT
}

main() {
local repo="$1"

{
# Write output header
cat <<-TYPESCRIPT
const languages: {[index: string]: any} = {
TYPESCRIPT

# Write export for each language
get-language-info "${repo}" \
| while read -r language query example; do
export-language "${language}" "${query}" "${example}"
done

# Write output footer
cat <<-TYPESCRIPT
};

export default languages;
TYPESCRIPT
} > languages_export.ts

stderr "${GREEN}" "Done! All languages have been exported"
}

(( $# != 1 )) && usage
main "$@"
Loading