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
15 changes: 15 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,20 @@ jobs:
if: matrix.build_playground
run: yarn workspace playground test

- name: Stage PR dev playground compiler bundle
if: ${{ matrix.build_playground && github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master' && github.event.pull_request.head.repo.full_name == github.repository }}
env:
PLAYGROUND_PREVIEW_ID: pr-${{ github.event.pull_request.number }}
run: yarn workspace dev-playground stage-local-bundle "$PLAYGROUND_PREVIEW_ID"

- name: "Upload artifacts: PR dev playground compiler bundle"
if: ${{ matrix.build_playground && github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'master' && github.event.pull_request.head.repo.full_name == github.repository }}
uses: actions/upload-artifact@v7
with:
name: dev-playground-pr-${{ github.event.pull_request.number }}-bundle
path: packages/dev-playground/public/playground-bundles/pr-${{ github.event.pull_request.number }}
if-no-files-found: error

- name: Stage dev playground compiler bundle
if: ${{ matrix.build_playground && github.event_name == 'push' && github.ref == 'refs/heads/master' }}
run: yarn workspace dev-playground stage-master-bundle
Expand Down Expand Up @@ -457,6 +471,7 @@ jobs:
env:
VITE_DEFAULT_COMPILER_VERSION: master
VITE_COMPILER_VERSIONS: '[{"id":"master","label":"master"}]'
VITE_COMPILER_PREVIEW_ROOT: https://cdn.rescript-lang.org/dev-playground-bundles
GITHUB_PAGES_PATH: dev-playground
PLAYGROUND_BUNDLE_ID: master
steps:
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/playground_preview_cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Playground Preview Cleanup

on:
pull_request_target:
branches: [master]
types: [closed]

jobs:
cleanup:
if: ${{ github.event.pull_request.head.repo.full_name == github.repository }}
runs-on: ubuntu-24.04
steps:
- name: Setup Rclone
uses: cometkim/rclone-actions/setup-rclone@main

- name: Configure Rclone remote
uses: cometkim/rclone-actions/configure-remote/s3-provider@main
with:
name: rescript
provider: Cloudflare
endpoint: https://${{ vars.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
access-key-id: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
secret-access-key: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
acl: private

- name: Delete preview bundle
continue-on-error: true
run: rclone purge "rescript:cdn-assets/dev-playground-bundles/pr-${{ github.event.pull_request.number }}"
60 changes: 60 additions & 0 deletions .github/workflows/playground_preview_upload.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Playground Preview Upload

on:
workflow_run:
workflows: [CI]
types: [completed]

jobs:
upload:
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_repository.full_name == github.repository && github.event.workflow_run.pull_requests[0].base.ref == 'master' }}
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
pull-requests: write
env:
PLAYGROUND_PREVIEW_ID: pr-${{ github.event.workflow_run.pull_requests[0].number }}
steps:
- name: Download preview bundle artifact
uses: actions/download-artifact@v8
with:
name: dev-playground-pr-${{ github.event.workflow_run.pull_requests[0].number }}-bundle
path: dev-playground-preview-bundle
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Setup Rclone
uses: cometkim/rclone-actions/setup-rclone@main

- name: Configure Rclone remote
uses: cometkim/rclone-actions/configure-remote/s3-provider@main
with:
name: rescript
provider: Cloudflare
endpoint: https://${{ vars.CLOUDFLARE_ACCOUNT_ID }}.r2.cloudflarestorage.com
access-key-id: ${{ secrets.CLOUDFLARE_R2_ACCESS_KEY_ID }}
secret-access-key: ${{ secrets.CLOUDFLARE_R2_SECRET_ACCESS_KEY }}
acl: private

- name: Upload preview bundle
run: |
rclone sync \
--stats 5 \
--checkers 5000 \
--transfers 8 \
--buffer-size 128M \
--s3-no-check-bucket \
--s3-chunk-size 128M \
--s3-upload-concurrency 8 \
--fast-list \
"dev-playground-preview-bundle" \
"rescript:cdn-assets/dev-playground-bundles/${PLAYGROUND_PREVIEW_ID}/bundle"

- name: Comment playground preview URL
uses: thollander/actions-comment-pull-request@v3
with:
pr-number: ${{ github.event.workflow_run.pull_requests[0].number }}
comment-tag: dev-playground-preview
message: |
Developer playground preview: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/dev-playground/?version=pr-${{ github.event.workflow_run.pull_requests[0].number }}
2 changes: 2 additions & 0 deletions packages/dev-playground/src/Bindings.res
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module Env = {
external viteDefaultCompilerVersion: option<string> =
"import.meta.env.VITE_DEFAULT_COMPILER_VERSION"
@val external viteCompilerVersions: option<string> = "import.meta.env.VITE_COMPILER_VERSIONS"
@val
external viteCompilerPreviewRoot: option<string> = "import.meta.env.VITE_COMPILER_PREVIEW_ROOT"
@val external viteBaseUrl: option<string> = "import.meta.env.BASE_URL"
}

Expand Down
70 changes: 65 additions & 5 deletions packages/dev-playground/src/CompilerApi.res
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
type compilerVersion = {
versionId: string,
versionLabel: string,
versionRoot: option<string>,
}

module Version = {
type t = {
id: string,
Expand All @@ -10,12 +16,28 @@ module Version = {
| _ => None
}

let normalizeRoot = root =>
if root->String.endsWith("/") {
root->String.slice(~start=0, ~end=root->String.length - 1)
} else {
root
}

let toPublic = (version: compilerVersion): t => {
id: version.versionId,
label: version.versionLabel,
}

let fromJson = json =>
switch json {
| JSON.Object(item) =>
let? Some(id) = item->jsonStringField("id")
let? Some(label) = item->jsonStringField("label")
Some({id, label})
Some({
versionId: id,
versionLabel: label,
versionRoot: item->jsonStringField("root")->Option.map(normalizeRoot),
})
| _ => None
}
}
Expand Down Expand Up @@ -86,7 +108,7 @@ let pathFromBase = relativePath => {
}

let parseCompilerVersions = defaultVersion => {
let fallback = [{Version.id: defaultVersion, label: defaultVersion}]
let fallback = [{versionId: defaultVersion, versionLabel: defaultVersion, versionRoot: None}]
switch Env.viteCompilerVersions {
| None | Some("") => fallback
| Some(versionJson) =>
Expand All @@ -100,8 +122,13 @@ let parseCompilerVersions = defaultVersion => {
}
}

let availableCompilerVersions = parseCompilerVersions(defaultConfig.compilerVersion)
let compilerVersions = parseCompilerVersions(defaultConfig.compilerVersion)
let availableCompilerVersions = compilerVersions->Array.map(Version.toPublic)
let compilerRoot = pathFromBase("playground-bundles")
let compilerPreviewRoot = switch Env.viteCompilerPreviewRoot {
| Some(root) => root === "" ? None : Some(root->Version.normalizeRoot)
| None => None
}
let loadedScripts: Map.t<string, promise<unit>> = Map.make()
let compilerApis: Map.t<string, compilerApi> = Map.make()
let compilers: Map.t<string, compilerInstance> = Map.make()
Expand All @@ -116,6 +143,41 @@ let hasFunction = (value, name) =>

let versionOrDefault = version => version === "" ? defaultConfig.compilerVersion : version

let isPreviewVersion = version => version->String.search(/^pr-[0-9]+$/) === 0

let previewVersionRoot = version =>
switch compilerPreviewRoot {
| Some(root) if version->isPreviewVersion => Some(`${root}/${version}/bundle`)
| _ => None
}

let versionRoot = version => {
let selectedVersion = versionOrDefault(version)
switch compilerVersions->Array.findMap(version =>
version.versionId === selectedVersion ? version.versionRoot : None
) {
| Some(root) => root
| None =>
switch selectedVersion->previewVersionRoot {
| Some(root) => root
| None => `${compilerRoot}/${selectedVersion}`
}
}
}

let isConfiguredVersion = version =>
compilerVersions->Array.some(compilerVersion => compilerVersion.versionId === version)

let isLoadableVersion = version =>
version->isConfiguredVersion || version->previewVersionRoot->Option.isSome

let selectableCompilerVersions = activeVersion =>
if activeVersion->isConfiguredVersion || !(activeVersion->previewVersionRoot->Option.isSome) {
availableCompilerVersions
} else {
Array.concat(availableCompilerVersions, [{Version.id: activeVersion, label: activeVersion}])
}

let createScriptLoadPromise = src =>
Promise.make((resolve, reject) => {
let document = Document.current
Expand All @@ -140,8 +202,6 @@ let loadScript = (src, ~cache=true) =>
createScriptLoadPromise(src)
}

let versionRoot = version => `${compilerRoot}/${versionOrDefault(version)}`

let applyConfig = (
instance,
~moduleSystem: PlaygroundConfig.moduleSystem,
Expand Down
4 changes: 3 additions & 1 deletion packages/dev-playground/src/CompilerApi.resi
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ type formatResult = result<string, failure>

let defaultConfig: PlaygroundConfig.t

let availableCompilerVersions: array<Version.t>
let selectableCompilerVersions: string => array<Version.t>

let isLoadableVersion: string => bool

let init: string => promise<info>

Expand Down
6 changes: 3 additions & 3 deletions packages/dev-playground/src/Main.res
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ module SettingsPanel = {
}}
>
{Node.fragment(
CompilerApi.availableCompilerVersions->Array.map(version =>
<option value=version.id> {Node.text(version.label)} </option>
),
CompilerApi.selectableCompilerVersions(
Signal.get(config).compilerVersion,
)->Array.map(version => <option value=version.id> {Node.text(version.label)} </option>),
)}
</select>
</section>
Expand Down
12 changes: 3 additions & 9 deletions packages/dev-playground/src/UrlState.res
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,10 @@ let queryExperimentalFeatures = defaultExperimentalFeatures =>
| _ => defaultExperimentalFeatures
}

let queryConfig = (
~defaultConfig: PlaygroundConfig.t,
~availableCompilerVersions: array<CompilerApi.Version.t>,
) => {
let queryConfig = (~defaultConfig: PlaygroundConfig.t) => {
let requestedCompilerVersion = queryCompilerVersion(defaultConfig.compilerVersion)
let compilerVersion =
availableCompilerVersions->Array.some(version => version.id === requestedCompilerVersion)
requestedCompilerVersion->CompilerApi.isLoadableVersion
? requestedCompilerVersion
: defaultConfig.compilerVersion

Expand All @@ -106,10 +103,7 @@ let queryConfig = (

let init = async (~defaultSource): state => {
let source = await initialSource(defaultSource)
let config = queryConfig(
~defaultConfig=CompilerApi.defaultConfig,
~availableCompilerVersions=CompilerApi.availableCompilerVersions,
)
let config = queryConfig(~defaultConfig=CompilerApi.defaultConfig)
{source, config}
}

Expand Down
Loading