From ebf107043437e917365911ef6bcf9e790bd5fb0e Mon Sep 17 00:00:00 2001 From: Adam Wright Date: Sat, 3 Oct 2026 15:38:04 +0000 Subject: [PATCH 1/2] Publish each library's build to a branch, for use before npm Until the libraries are released to npm, a passing push to main puts each built library on its own branch -- dist/ -- with the package at the root, which npm installs as a git dependency. Only commits whose tests passed are published, one publish at a time, and each build is a commit on top of the last. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish-builds.yml | 84 ++++++++++++++++++++++++++++ README.md | 14 +++++ 2 files changed, 98 insertions(+) create mode 100644 .github/workflows/publish-builds.yml diff --git a/.github/workflows/publish-builds.yml b/.github/workflows/publish-builds.yml new file mode 100644 index 0000000..2d5ac67 --- /dev/null +++ b/.github/workflows/publish-builds.yml @@ -0,0 +1,84 @@ +name: Publish builds + +# Until the libraries are released to npm, each one's build is kept on its own +# branch -- dist/ngx-reactome-cytoscape-style, dist/ngx-reactome-style, +# dist/ngx-reactome-diagram -- with the package at the branch root, so another +# project can install it straight from GitHub: +# +# "ngx-reactome-cytoscape-style": +# "github:reactome/ngx-reactome-base#dist/ngx-reactome-cytoscape-style" +# +# npm's lockfile pins the commit, so a consumer moves to a newer build only +# when it updates the dependency. +# +# Runs only after Tests has passed for a commit on main: a build that failed +# its tests is never published. +on: + workflow_run: + workflows: ['Tests'] + types: [completed] + branches: + - main + # To publish again without a new commit. + workflow_dispatch: + +permissions: + contents: write + +# One publish at a time, so two never race to push the same branch. +concurrency: + group: publish-builds + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + if: >- + github.event_name == 'workflow_dispatch' || + (github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'push') + steps: + - uses: actions/checkout@v7 + with: + # The commit that was tested, not whatever main points at now. + ref: ${{ github.event.workflow_run.head_sha || github.sha }} + + - uses: actions/setup-node@v7 + with: + node-version-file: .nvmrc + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Build the libraries + run: npm run build:libs + + - name: Push each build to its branch + env: + SOURCE: ${{ github.event.workflow_run.head_sha || github.sha }} + REMOTE: https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git + run: | + set -euo pipefail + for lib in ngx-reactome-cytoscape-style ngx-reactome-style ngx-reactome-diagram; do + branch="dist/$lib" + cd "dist/$lib" + git init -q + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + # Each build follows the previous one, so the branch keeps a + # history of what was published and from which commit. + if git ls-remote --exit-code "$REMOTE" "refs/heads/$branch" >/dev/null; then + git fetch -q --depth 1 "$REMOTE" "$branch" + git reset -q --soft FETCH_HEAD + fi + git add -A + if git diff --cached --quiet && git rev-parse -q --verify HEAD >/dev/null; then + echo "$lib: unchanged" + else + git commit -q -m "Build of $lib from ${SOURCE}" + git push -q "$REMOTE" "HEAD:refs/heads/$branch" + echo "$lib: published to $branch" + fi + cd - >/dev/null + done diff --git a/README.md b/README.md index c7c2198..a1e7017 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,20 @@ Run `ng generate component component-name` to generate a new component. You can Run `npm run build` to build the libraries and the demo app, in the order they depend on each other (`npm run build:libs` for the libraries alone). The build artifacts are stored in `dist/`. +## Using the libraries before they are on npm + +Each push to `main` that passes its tests publishes the built libraries to +branches of this repository, one per library, with the package at the branch +root. Install one from there: + +```json +"ngx-reactome-cytoscape-style": "github:reactome/ngx-reactome-base#dist/ngx-reactome-cytoscape-style", +"ngx-reactome-style": "github:reactome/ngx-reactome-base#dist/ngx-reactome-style", +"ngx-reactome-diagram": "github:reactome/ngx-reactome-base#dist/ngx-reactome-diagram" +``` + +The lockfile pins the commit; `npm update ` moves to the latest build. + ## Running unit tests Run `npm test` to run every project's unit tests with [Vitest](https://vitest.dev) through Angular's unit-test builder, or `ng test ` for one. The diagram's tests use the built style library, so run `npm run build:libs` first. From d27a79b32a47e8a56f919112eed634aca64b10c2 Mon Sep 17 00:00:00 2001 From: Adam Wright Date: Sat, 3 Oct 2026 15:42:37 +0000 Subject: [PATCH 2/2] Publish only main's tested tip, without the token on disk during the build From review: a manual run from another branch would have published that branch untested; checkout left the write token in .git/config while npm install scripts and the build ran; and test runs finishing out of order could publish an older build over a newer one. Manual runs are main only, the token reaches only the push step, and a commit that is no longer main's tip is not published. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/publish-builds.yml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-builds.yml b/.github/workflows/publish-builds.yml index 2d5ac67..2ff8a49 100644 --- a/.github/workflows/publish-builds.yml +++ b/.github/workflows/publish-builds.yml @@ -19,7 +19,8 @@ on: types: [completed] branches: - main - # To publish again without a new commit. + # To publish main again without a new commit. Only from main: a run from + # another branch would build and publish that branch, untested. workflow_dispatch: permissions: @@ -34,7 +35,7 @@ jobs: publish: runs-on: ubuntu-latest if: >- - github.event_name == 'workflow_dispatch' || + (github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main') || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'push') steps: @@ -42,6 +43,9 @@ jobs: with: # The commit that was tested, not whatever main points at now. ref: ${{ github.event.workflow_run.head_sha || github.sha }} + # No token left in .git/config while npm install scripts and the + # build run: only the push step below has it. + persist-credentials: false - uses: actions/setup-node@v7 with: @@ -60,6 +64,14 @@ jobs: REMOTE: https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git run: | set -euo pipefail + # Only main's current commit. Test runs finish out of order, and an + # older run finishing (or re-run) later must not publish over a newer + # build. + tip=$(git ls-remote "$REMOTE" refs/heads/main | cut -f1) + if [ "$tip" != "$SOURCE" ]; then + echo "$SOURCE is no longer main's tip ($tip): not publishing." + exit 0 + fi for lib in ngx-reactome-cytoscape-style ngx-reactome-style ngx-reactome-diagram; do branch="dist/$lib" cd "dist/$lib"