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
146 changes: 141 additions & 5 deletions .github/workflows/javascript.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ on:
branches:
- main
pull_request:
types: [opened, synchronize, labeled]
pull_request_review:
types: [submitted]
types: [opened, synchronize, labeled, closed]
release:
types: [published]

Expand All @@ -17,6 +15,7 @@ permissions:

jobs:
main:
if: github.event.action != 'closed'
env:
GH_TOKEN: ${{ github.token }}

Expand Down Expand Up @@ -71,6 +70,8 @@ jobs:
- name: Run `build` for all NX packages
env:
RELEASE_BUILD: ${{ github.event_name == 'release' && 'true' || 'false' }}
GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
GITHUB_PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: yarn build

- name: Run `test` for all NX packages
Expand All @@ -84,6 +85,15 @@ jobs:
if-no-files-found: error
retention-days: 1

- name: Upload docs artifact
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: docs-preview
path: docs/.vitepress/dist
if-no-files-found: error
retention-days: 1

# NX is not able to properly detect affected changes if things change in C source or the WASM build
#
# - name: Set NX SHAs
Expand Down Expand Up @@ -136,8 +146,6 @@ jobs:
if: |
(github.repository == 'marcoroth/herb' && github.event_name == 'pull_request' && github.event.pull_request.user.login == github.repository_owner) ||
(github.repository == 'marcoroth/herb' && github.event_name == 'pull_request' && contains(github.event.pull_request.labels.*.name, 'release-preview')) ||
(github.repository == 'marcoroth/herb' && github.event_name == 'pull_request_review' && github.event.review.state == 'approved') ||
(github.repository == 'marcoroth/herb' && github.event_name == 'pull_request_review' && contains(github.event.pull_request.labels.*.name, 'release-preview')) ||
(github.repository == 'marcoroth/herb' && github.event_name == 'push' && github.ref == 'refs/heads/main')

runs-on: ubuntu-latest
Expand Down Expand Up @@ -213,3 +221,131 @@ jobs:
run: |
cd javascript/packages/vscode
npx ovsx publish -p $OVSX_PAT

deploy-preview:
name: Deploy docs preview to Cloudflare Pages
needs: [main, preview-check]
if: needs.preview-check.outputs.has-permissions == 'true'
runs-on: ubuntu-latest

permissions:
contents: read
deployments: write
pull-requests: write

steps:
- name: Download docs artifact
uses: actions/download-artifact@v4
with:
name: docs-preview
path: dist

- name: Deploy to Cloudflare Pages
id: deploy
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: herb-tools
directory: dist
gitHubToken: ${{ secrets.GITHUB_TOKEN }}

- name: Add comment with preview URL
uses: actions/github-script@v7
with:
script: |
const previewUrl = '${{ steps.deploy.outputs.url }}';
const comment = `### 🌿 Interactive Playground and Documentation Preview

A preview deployment has been built for this pull request. Try out the changes live in the interactive playground:

- **[Playground Preview](${previewUrl}/playground)**
- **[Documentation Preview](${previewUrl})**
- **[Website Preview](${previewUrl})**

---
<sub>🌱 Grown from commit [\`${context.payload.pull_request.head.sha.substring(0, 7)}\`](https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.payload.pull_request.head.sha})</sub>`;

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('🌿 Interactive Playground and Documentation Preview')
);

if (botComment) {
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: comment
});
} else {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: comment
});
}

cleanup-preview:
name: Cleanup docs preview deployment
if: github.event_name == 'pull_request' && github.event.action == 'closed'
runs-on: ubuntu-latest

permissions:
pull-requests: write

steps:
- name: Delete Cloudflare Pages deployment
env:
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
BRANCH_NAME: ${{ github.event.pull_request.head.ref }}
run: |
DEPLOYMENTS=$(curl -s -X GET \
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/herb-tools/deployments" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json")

DEPLOYMENT_ID=$(echo "$DEPLOYMENTS" | jq -r ".result[] | select(.deployment_trigger.metadata.branch == \"$BRANCH_NAME\") | .id" | head -n 1)

if [ -n "$DEPLOYMENT_ID" ]; then
echo "Deleting deployment $DEPLOYMENT_ID for branch $BRANCH_NAME"
curl -X DELETE \
"https://api.cloudflare.com/client/v4/accounts/${CLOUDFLARE_ACCOUNT_ID}/pages/projects/herb-tools/deployments/$DEPLOYMENT_ID" \
-H "Authorization: Bearer ${CLOUDFLARE_API_TOKEN}" \
-H "Content-Type: application/json"
else
echo "No deployment found for branch $BRANCH_NAME"
fi

- name: Update PR comment
uses: actions/github-script@v7
with:
script: |
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
});

const botComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes('🌿 Interactive Playground and Documentation Preview')
);

if (botComment) {
const updatedComment = botComment.body + '\n\n---\n\n✅ Preview deployment has been cleaned up.';
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: botComment.id,
body: updatedComment
});
}
24 changes: 17 additions & 7 deletions playground/src/controllers/playground_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -778,16 +778,26 @@ export default class extends Controller {
if (this.hasCommitHashTarget) {
if (typeof __COMMIT_INFO__ !== 'undefined') {
const commitInfo = __COMMIT_INFO__
const githubUrl = `https://github.com/marcoroth/herb/commit/${commitInfo.hash}`

if (commitInfo.ahead > 0) {
this.commitHashTarget.textContent = `${commitInfo.tag} (+${commitInfo.ahead} commits) ${commitInfo.hash}`
if (commitInfo.prNumber) {
const prUrl = `https://github.com/marcoroth/herb/pull/${commitInfo.prNumber}`
const commitUrl = `https://github.com/marcoroth/herb/commit/${commitInfo.hash}`

this.commitHashTarget.textContent = `PR #${commitInfo.prNumber} @ ${commitInfo.hash}`
this.commitHashTarget.href = prUrl
this.commitHashTarget.title = `View PR #${commitInfo.prNumber} on GitHub (commit ${commitInfo.hash})`
} else {
this.commitHashTarget.textContent = `${commitInfo.tag} ${commitInfo.hash}`
}
const githubUrl = `https://github.com/marcoroth/herb/commit/${commitInfo.hash}`

if (commitInfo.ahead > 0) {
this.commitHashTarget.textContent = `${commitInfo.tag} (+${commitInfo.ahead} commits) ${commitInfo.hash}`
} else {
this.commitHashTarget.textContent = `${commitInfo.tag} ${commitInfo.hash}`
}

this.commitHashTarget.href = githubUrl
this.commitHashTarget.title = `View commit ${commitInfo.hash} on GitHub`
this.commitHashTarget.href = githubUrl
this.commitHashTarget.title = `View commit ${commitInfo.hash} on GitHub`
}
} else {
this.commitHashTarget.textContent = 'unknown'
this.commitHashTarget.removeAttribute('href')
Expand Down
60 changes: 35 additions & 25 deletions playground/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,37 @@ function getCommitInfo() {
let hash = "unknown"
let tag = "unknown"
let ahead = 0
let prNumber = null

try {
try {
hash = execSync("git rev-parse --short HEAD", { encoding: "utf8" }).trim()
} catch (hashError) {
if (process.env.GITHUB_SHA) {
hash = process.env.GITHUB_SHA.substring(0, 7)
}
const isGitHubActions = process.env.GITHUB_ACTIONS === 'true'

if (isGitHubActions) {
if (process.env.GITHUB_EVENT_NAME === 'pull_request' && process.env.GITHUB_PR_HEAD_SHA) {
hash = process.env.GITHUB_PR_HEAD_SHA.substring(0, 8)
prNumber = process.env.GITHUB_PR_NUMBER
tag = `PR #${prNumber}`
ahead = 0
console.log(`GitHub Actions PR build: hash=${hash}, PR=${prNumber}`)
} else {
hash = process.env.GITHUB_SHA?.substring(0, 8) || "unknown"
}

if (process.env.GITHUB_REF?.startsWith('refs/tags/')) {
tag = process.env.GITHUB_REF.replace('refs/tags/', '')
ahead = 0
console.log(`GitHub Actions tag build: hash=${hash}, tag=${tag}`)
} else {
tag = process.env.GITHUB_REF_NAME || "unknown"
ahead = 0
console.log(`GitHub Actions branch build: hash=${hash}, ref=${tag}`)
}

return { hash, tag, ahead, prNumber }
}

try {
hash = execSync("git rev-parse --short=8 HEAD", { encoding: "utf8" }).trim()

try {
execSync("git fetch --tags --force", { stdio: 'ignore' })
tag = execSync("git describe --tags --abbrev=0", { encoding: "utf8" }).trim()
Expand All @@ -27,36 +48,25 @@ function getCommitInfo() {
}
} catch (tagError) {
console.warn("Could not get git tag info:", tagError.message)

if (process.env.GITHUB_REF) {
if (process.env.GITHUB_REF.startsWith('refs/tags/')) {
tag = process.env.GITHUB_REF.replace('refs/tags/', '')
ahead = 0
} else if (process.env.GITHUB_REF_NAME) {
tag = process.env.GITHUB_REF_NAME
}
}
tag = "dev"
}

console.log(`Git info: hash=${hash}, tag=${tag}, ahead=${ahead}`)
return { hash, tag, ahead }
console.log(`Local build: hash=${hash}, tag=${tag}, ahead=${ahead}`)
} catch (error) {
console.warn("Could not get git commit info:", error.message)
return {
hash: process.env.GITHUB_SHA?.substring(0, 7) || "unknown",
tag: process.env.GITHUB_REF_NAME || "unknown",
ahead: 0
}
hash = "unknown"
tag = "unknown"
}

return { hash, tag, ahead, prNumber }
}

export default defineConfig({
define: {
__COMMIT_INFO__: JSON.stringify(getCommitInfo()),
},
server: {
port: process.env.PORT ? parseInt(process.env.PORT) : 5173,
allowedHosts: ["playground.herb-tools.dev"],
port: process.env.PORT ? parseInt(process.env.PORT) : 5173
},
plugins: [],
})
Loading