Skip to content
Open
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
68 changes: 68 additions & 0 deletions .github/actions/yarn-install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: 'Install dependencies'
description: >
Set up the Node version from .nvmrc and get node_modules in place, restoring
it from cache when nothing that shapes the tree has changed.

runs:
using: composite
steps:
# The runner's OS release, not just `runner.os`. Both ubuntu-22.04 and
# ubuntu-24.04 report "Linux", and this repo uses both, so keying on
# runner.os alone would let a tree installed on one be restored on the
# other. The prebuilt native binaries we pull (rollup, lmdb, lightningcss,
# esbuild) target an old glibc and would survive that today, but nothing
# guarantees the next dependency will.
- id: os
shell: bash
run: |
if [ -r /etc/os-release ]; then
. /etc/os-release
echo "id=${ID}${VERSION_ID}" >> "$GITHUB_OUTPUT"
else
echo "id=${RUNNER_OS}" >> "$GITHUB_OUTPUT"
fi

# First, because whether this hits decides if restoring the ~480 MB yarn
# download cache below is worth doing at all.
- id: node_modules
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: node_modules
# .nvmrc is in the key because the tree records the Node ABI it was
# built for, and yarn.lock because it is what the tree must match.
#
# No restore-keys on purpose. A tree from a different lockfile is not a
# useful starting point: yarn has to reconcile it, and an optional
# dependency that is no longer selected can survive the reconcile.
# Exact match or a clean install; there is no useful middle.
key: ${{ steps.os.outputs.id }}-${{ runner.arch }}-node-modules-${{ hashFiles('.nvmrc', 'yarn.lock') }}

- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version-file: '.nvmrc'
# Deliberately no `cache: yarn`; the two steps below do it conditionally.

# The yarn download cache only speeds up an install that actually downloads.
# It is ~480 MB in this repo, so restoring it on a run whose node_modules
# already hit costs more than the 2s install it would be accelerating.
- id: yarn_cache_dir
if: steps.node_modules.outputs.cache-hit != 'true'
shell: bash
run: echo "path=$(yarn cache dir)" >> "$GITHUB_OUTPUT"

- if: steps.node_modules.outputs.cache-hit != 'true'
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ${{ steps.yarn_cache_dir.outputs.path }}
key: ${{ steps.os.outputs.id }}-${{ runner.arch }}-yarn-${{ hashFiles('yarn.lock') }}
# Here restore-keys IS right: a partial download cache is still a
# head start, and yarn verifies every package against the lockfile.
restore-keys: |
${{ steps.os.outputs.id }}-${{ runner.arch }}-yarn-

# Always, hit or miss. On a hit yarn checks node_modules/.yarn-integrity
# against the lockfile and exits in about two seconds with "Already
# up-to-date", and the `prepare` script still runs. The cache is an
# accelerator; yarn stays the source of truth.
- shell: bash
run: yarn --frozen-lockfile
39 changes: 39 additions & 0 deletions .github/workflows/bld_mvn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ on:
required: false
default: "default"
type: string
deploy:
description: 'Whether to upload the WAR to the artifact repository. Set false for a dry run.'
required: false
default: true
type: boolean

workflow_dispatch:
inputs:
Expand All @@ -48,6 +53,11 @@ on:
required: false
default: "default"
type: string
deploy:
description: 'Whether to upload the WAR to the artifact repository. Set false for a dry run.'
required: false
default: true
type: boolean

jobs:
bld_mvn:
Expand All @@ -72,6 +82,27 @@ jobs:
# NOTE: history does not include tags!
fetch-depth: 100

# Build the Angular app here rather than letting frontend-maven-plugin do
# it: this reuses the runner's Node and the cached node_modules instead of
# downloading Node and installing from cold inside maven. The maven build
# below skips the plugin's node/yarn goals and just packages ./dist.
- uses: ./.github/actions/yarn-install

# The WAR must be built from formatted source. That is already guaranteed
# by construction: the `format` job applies prettier on the PR branch and
# is a required check, so the commit that merges is the formatted one.
# This asserts it anyway, and fails fast if anything ever reaches main
# without passing that gate (an admin bypass, a direct push).
- name: assert the source is formatted
run: yarn format:check

- name: build the Angular app (prebuild + postbuild included)
run: yarn build

# The WAR is a verbatim copy of ./dist, so validate it before packaging.
- run: yarn build:manifest:check
- run: yarn build:verify

- name: find next version
id: version
uses: ORCID/version-bump-action@main
Expand Down Expand Up @@ -117,10 +148,15 @@ jobs:

- name: build our project
run: |
# skip.installyarn skips the install-node-and-yarn goal and skip.yarn
# skips both `yarn` goals of frontend-maven-plugin: ./dist was already
# built by the `yarn build` step above. pom.xml is left untouched so
# local `mvn` builds still run the full frontend chain.
mvn -T 1C --batch-mode \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn \
--file "pom.xml" \
--activate-profiles prod -Dnodejs.workingDirectory=. \
-Dskip.installyarn=true -Dskip.yarn=true \
package -Dmaven.test.skip

echo "------------------------------------------------------"
Expand All @@ -129,7 +165,10 @@ jobs:
env:
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'

# Skipped by the ci_only dry run: it proves the WAR still builds without
# publishing an artifact nobody asked for.
- name: deploy same artifact for all environments
if: ${{ inputs.deploy }}
run: |
WAR_FILE="target/orcid-web-frontend-prod.war"
REPO_URL="${ARTIFACT_URL}${ARTIFACT_REPO_PATH}"
Expand Down
56 changes: 31 additions & 25 deletions .github/workflows/bld_test_rel_tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ on:
type: boolean
required: false
default: false
deploy:
description: 'Whether to upload the WAR and push the i18n source. Set false for a dry run.'
type: boolean
required: false
default: true

workflow_dispatch:
inputs:
Expand Down Expand Up @@ -62,44 +67,43 @@ on:
type: boolean
required: false
default: false
deploy:
description: 'Whether to upload the WAR and push the i18n source. Set false for a dry run.'
type: boolean
required: false
default: true

# cancel running job if another commit comes in
concurrency:
group: main-${{ github.ref }}-1
cancel-in-progress: true

jobs:
format_i18n:
uses: ./.github/workflows/format_i18n.yml
secrets: inherit # pass all secrets for pushing

format_prettier:
uses: ./.github/workflows/format_prettier.yml
secrets: inherit # pass all secrets for pushing
# Extract messages.xlf from the code and push it to Transifex. Off the
# critical path: nothing downstream depends on it.
# Formatting and unit tests are PR gates (pr.yml), not main gates: branch
# protection requires an up-to-date, green branch, so main re-tests a tree
# that has already passed.
push_i18n_source:
if: ${{ github.ref == 'refs/heads/main' && inputs.deploy }}
uses: ./.github/workflows/push_i18n_source.yml
secrets:
TRANSIFEX_TOKEN: ${{ secrets.TRANSIFEX_TOKEN }}

##############################################################################

lint:
uses: ./.github/workflows/lint.yml
needs:
- format_i18n
- format_prettier

test_yarn:
uses: ./.github/workflows/test_yarn.yml
needs:
- format_i18n
- format_prettier

##############################################################################
# uses maven to build via yarn into a war file
# No `needs: lint`. lint is a required check on the pull request (pr.yml
# produces `lint / pre-commit`), so main is re-running something the merge
# already gated on. Running it in parallel takes ~40s off the critical path;
# rel_tag still waits for it, so nothing is tagged or released on a lint failure.
bld_mvn:
uses: ./.github/workflows/bld_mvn.yml
secrets: inherit # pass all secrets for uploading assets
needs:
- lint
- format_i18n
- format_prettier
permissions:
checks: write
contents: read
Expand All @@ -109,15 +113,12 @@ jobs:
version_tag: ${{ inputs.version_tag }}
bump: ${{ inputs.bump }}
ref: ${{ inputs.ref }}
deploy: ${{ inputs.deploy }}

bld_docker:
if: ${{ inputs.run_docker }}
uses: ./.github/workflows/bld_docker.yml
secrets: inherit # pass all secrets for uploading assets
needs:
- lint
- format_i18n
- format_prettier
permissions:
checks: write
contents: read
Expand All @@ -130,10 +131,15 @@ jobs:

##############################################################################

# Gated on lint as well as the WAR: the build can run in parallel, but nothing
# gets tagged or released while lint is red. lint (~30s) always finishes long
# before bld_mvn (~4min), so this adds no latency.
rel_tag:
uses: ./.github/workflows/rel_tag.yml
if: ${{ inputs.rel_tag }}
needs: bld_mvn
needs:
- bld_mvn
- lint
with:
version_tag: ${{ inputs.version_tag }}
bump: ${{ inputs.bump }}
Expand Down
25 changes: 19 additions & 6 deletions .github/workflows/bld_yarn.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
name: bld_yarn

# The job only builds; it calls no GitHub API.
permissions:
checks: write
contents: read
issues: read

on:
workflow_call:
Expand All @@ -20,9 +19,23 @@ jobs:
egress-policy: audit

- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
- uses: ./.github/actions/yarn-install

- uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
node-version: 'v20.x'
cache: 'yarn'
- run: yarn
path: .angular/cache
key: ${{ runner.os }}-ng-cache-${{ hashFiles('yarn.lock') }}-${{ github.sha }}
restore-keys: |
${{ runner.os }}-ng-cache-${{ hashFiles('yarn.lock') }}-

- run: yarn build

# Fails when the real build changes the shape of the deployed tree (a
# locale that stopped being emitted, a bundle that lost its locale
# suffix, a file that moved out of share-assets). Lazy-chunk count
# changes are reported but do not fail; see the helper for why.
- run: yarn build:manifest:check

# Resolves every asset URL and every chunk import in the real 21-locale
# tree through the production nginx rules. Catches what the fixture cannot.
- run: yarn build:verify
Loading
Loading