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
7 changes: 6 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@ jobs:
with:
node-version: "22"
architecture: 'x64' # fix for macos-latest
- run: npm ci
registry-url: 'https://npm.pkg.github.com'
scope: '@plexinc'
- name: npm ci
env:
NODE_AUTH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
run: npm ci
Comment thread
ljunkie marked this conversation as resolved.
- run: npm run preversion
191 changes: 191 additions & 0 deletions .github/workflows/xelp_npm_release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
name: Xelp npm Release

# Builds the current xelp/main, publishes it to GitHub Packages as
# @plexinc/<name>, then tags the commit and creates a GitHub release.
#
# Authentication is the workflow's own GITHUB_TOKEN, so there is no secret to
# provision or rotate. Consumers authenticate the way every other Plex client
# repo does, with a personal access token carrying read:packages.
Comment thread
ljunkie marked this conversation as resolved.
#
# This replaces xelp_shadow_release.yml, which committed dist/ to the xelp/dist
# branch and served the package to consumers through a git tag. Run one or the
# other, never both: they compute the same version string and so want the same
# tag, and the shadow release force pushes it.
#
# Keep the shadow release around until roku-client, the only consumer of these
# forks, is installing from the @plexinc package. Then delete it.
#

on:
workflow_dispatch:
inputs:
dryRun:
description: Build and pack, but do not publish, tag, or release.
type: boolean
default: false

# packages: write is the publish permission. contents: write is only for the
# tag and the release.
#
permissions:
contents: write
packages: write

jobs:
release:
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- name: Check out xelp/main
uses: actions/checkout@v5
with:
ref: xelp/main
fetch-depth: 0

- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: 20
registry-url: https://npm.pkg.github.com
scope: '@plexinc'

- name: Configure git
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Work out the package name and version
id: release
run: |
set -euo pipefail

UPSTREAM_NAME=$(node -p "require('./package.json').name")

# Re-scope to @plexinc, dropping any existing scope, so
# @rokucommunity/bslint becomes @plexinc/bslint. GitHub Packages
# requires the scope to match the owner of this repository.
#
SCOPED_NAME="@plexinc/${UPSTREAM_NAME##*/}"

# Version scheme, unchanged from the shadow release: the upstream major
# and minor, then the build date with the upstream patch appended, so
# 0.70.3 built on 2026-08-28 becomes 0.70.202608283.
#
CURRENT_VERSION=$(node -p "require('./package.json').version")
BASE_VERSION=${CURRENT_VERSION%%[-+]*}

IFS='.' read -r -a PARTS <<< "$BASE_VERSION"
if [ ${#PARTS[@]} -ne 3 ]; then
echo "::error::Version $CURRENT_VERSION is not MAJOR.MINOR.PATCH"
exit 1
fi

VERSION="${PARTS[0]}.${PARTS[1]}.$(date -u +'%Y%m%d')${PARTS[2]}"

{
echo "upstream_name=$UPSTREAM_NAME"
echo "scoped_name=$SCOPED_NAME"
echo "version=$VERSION"
echo "metadata_version=$VERSION+xelp-$(git rev-parse --short HEAD)"
} >> "$GITHUB_OUTPUT"

# Published versions are immutable and tags are no longer force-pushed, so
# a same day re-run would collide twice over. Fail before doing the work.
#
- name: Fail if this version is already published
env:
# Only the three steps that talk to the registry get the token: this
# one, the install, and the publish. Building, linting, testing and
# packing do not reach the network, so they do not need it. Add it to
# any new step that runs npm against the registry.
#
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SCOPED_NAME: ${{ steps.release.outputs.scoped_name }}
VERSION: ${{ steps.release.outputs.version }}
run: |
if npm view "$SCOPED_NAME@$VERSION" version >/dev/null 2>&1; then
echo "::error::$SCOPED_NAME@$VERSION is already published. Land another commit, or wait for tomorrow's date stamp."
exit 1
fi

# The upstream lockfile is what keeps the transitive dependencies on
# working versions, so install from it rather than re-resolving. A clean
# re-resolve floats vscode-languageserver-protocol onto an exports only
# release that the TypeScript build cannot import.
#
- name: Install dependencies
env:
# Dependencies can live in another repo's package, and a repository's
# own GITHUB_TOKEN cannot read those, so prefer the organization token.
# The fallback keeps this working in a fork that has no @plexinc
# dependencies, where the repo token is enough.
#
NODE_AUTH_TOKEN: ${{ secrets.GH_TOKEN || secrets.GITHUB_TOKEN }}
run: npm ci

- name: Build
run: npm run build

# The shadow release ran the lint and test suites as a side effect of
# npm version, which triggers the preversion script. Setting the version
# through npm pkg set does not run lifecycle scripts, so the gate runs
# here where a failure names the step that failed.
#
- name: Lint
run: npm run lint

- name: Test
run: npm test

# The rename happens here and is never committed to xelp/main, so a merge
# from upstream never has to resolve a changed package name. The repository
# URL is what links the package to this repo, and GitHub Packages rejects
# the publish if it points anywhere else.
#
- name: Rewrite the package metadata for the @plexinc scope
env:
SCOPED_NAME: ${{ steps.release.outputs.scoped_name }}
VERSION: ${{ steps.release.outputs.version }}
run: |
npm pkg set name="$SCOPED_NAME"
npm pkg set version="$VERSION"
npm pkg set repository.url="git+https://github.com/${{ github.repository }}.git"

- name: Publish to GitHub Packages
if: ${{ !inputs.dryRun }}
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm publish

- name: Pack without publishing
if: ${{ inputs.dryRun }}
run: npm pack --dry-run

- name: Tag the release
if: ${{ !inputs.dryRun }}
env:
VERSION: ${{ steps.release.outputs.version }}
METADATA_VERSION: ${{ steps.release.outputs.metadata_version }}
run: |
git tag -a "$VERSION" -m "Release $METADATA_VERSION"
git push origin "$VERSION"

- name: Create the GitHub release
if: ${{ !inputs.dryRun }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
UPSTREAM_NAME: ${{ steps.release.outputs.upstream_name }}
SCOPED_NAME: ${{ steps.release.outputs.scoped_name }}
VERSION: ${{ steps.release.outputs.version }}
METADATA_VERSION: ${{ steps.release.outputs.metadata_version }}
run: |
gh release create "$VERSION" \
--repo "$GITHUB_REPOSITORY" \
--title "$SCOPED_NAME $VERSION" \
--notes "Built from \`$METADATA_VERSION\`.

Consume it with an alias, so the package keeps its upstream name inside \`node_modules\`:

\`\`\`json
\"$UPSTREAM_NAME\": \"npm:$SCOPED_NAME@$VERSION\"
\`\`\`" \
--prerelease
3 changes: 3 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Use GitHub for @plexinc packages.
@plexinc:registry=https://npm.pkg.github.com/
//npm.pkg.github.com/:always-auth=true
Comment on lines +1 to +3
8 changes: 5 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"brighterscript-formatter": "dist/cli.js"
},
"dependencies": {
"brighterscript": "https://github.com/plexinc/brighterscript.git#0.70.202603123",
"brighterscript": "npm:@plexinc/brighterscript@^0.70.0",
"glob-all": "^3.3.0",
"jsonc-parser": "^3.0.0",
"source-map": "0.7.4",
Expand Down