@@ -3,8 +3,7 @@ name: Release Packages
33on :
44 workflow_run :
55 workflows : ["Tag on Merge"]
6- types :
7- - completed
6+ types : [completed]
87
98permissions :
109 id-token : write
@@ -14,49 +13,69 @@ jobs:
1413 publish :
1514 environment : npm-release
1615 runs-on : ubuntu-latest
16+ env :
17+ tags : " "
1718
1819 steps :
1920 - uses : actions/checkout@v4
2021 with :
2122 fetch-depth : 0
2223
24+ - name : Fetch all tags
25+ run : git fetch --tags
26+
27+ - name : Find all new package tags on this commit
28+ id : find_tags
29+ shell : bash
30+ run : |
31+ TAGS=$(git tag --points-at HEAD | grep -E '^@instructure.ai/.+@([0-9]+\.[0-9]+\.[0-9]+)$' || true)
32+
33+ # Output for conditionals in later steps
34+ echo "tags<<EOF" >> "$GITHUB_OUTPUT"
35+ echo "$TAGS" >> "$GITHUB_OUTPUT"
36+ echo "EOF" >> "$GITHUB_OUTPUT"
37+
38+ # Also set env var for shell scripts in later steps
39+ {
40+ echo "tags<<EOF"
41+ echo "$TAGS"
42+ echo "EOF"
43+ } >> "$GITHUB_ENV"
44+
45+ if [[ -z "$TAGS" ]]; then
46+ echo "No new matching tags found on this commit."
47+ fi
48+
49+ # Only set up Node/pnpm + caching if we actually have tags to release
2350 - name : Install pnpm
51+ if : steps.find_tags.outputs.tags != ''
2452 run : npm install -g pnpm
2553
2654 - uses : actions/setup-node@v4
55+ if : steps.find_tags.outputs.tags != ''
2756 with :
2857 node-version : ' 24'
2958 registry-url : ' https://registry.npmjs.org'
3059 cache : ' pnpm'
60+ cache-dependency-path : |
61+ pnpm-lock.yaml
62+ **/pnpm-lock.yaml
3163
64+ # Pre-create the ACTUAL pnpm store so post-job cache save never errors
3265 - name : Ensure pnpm store exists for caching
66+ if : steps.find_tags.outputs.tags != ''
67+ shell : bash
3368 run : |
34- mkdir -p ~/.pnpm-store
35-
36- - name : Install pnpm
37- run : npm install -g pnpm
38-
39- - name : Fetch all tags
40- run : git fetch --tags
41-
42- - name : Find all new package tags on this commit
43- id : find_tags
44- run : |
45- TAGS=$(git tag --points-at HEAD | grep -E '^@instructure.ai/.+@([0-9]+\.[0-9]+\.[0-9]+)$' || true)
46- if [[ -z "$TAGS" ]]; then
47- echo "No new matching tags found on this commit."
48- exit 0
49- fi
50- # Save tags list for next steps
51- echo "tags<<EOF" >> $GITHUB_ENV
52- echo "$TAGS" >> $GITHUB_ENV
53- echo "EOF" >> $GITHUB_ENV
69+ STORE="$(pnpm store path)"
70+ echo "pnpm store path: $STORE"
71+ mkdir -p "$STORE"
5472
5573 - name : Release each package tag
56- if : env .tags != ''
74+ if : steps.find_tags.outputs .tags != ''
5775 env :
58- tags : ${{ env.tags }}
76+ tags : ${{ env.tags }} # comes from $GITHUB_ENV we set above
5977 GH_TOKEN : ${{ secrets.GITHUB_TOKEN }}
78+ shell : bash
6079 run : |
6180 set -euo pipefail
6281
@@ -76,25 +95,17 @@ jobs:
7695 # Enable vite-node loader using the register() API
7796 export NODE_OPTIONS="--import=${{ github.workspace }}/scripts/loader.mjs"
7897
79- # Build
80- if [ "$PKG_NAME" = "shared-configs" ]; then
81- echo "Skipping build for @instructure.ai/shared-configs."
82- else
98+ # Build & test (skip for shared-configs)
99+ if [ "$PKG_NAME" != "shared-configs" ]; then
83100 echo "Building package: $PKG_NAME"
84101 CI=1 pnpm build package "$PKG_NAME"
85- fi
86-
87- # Test
88- if [ "$PKG_NAME" = "shared-configs" ]; then
89- echo "Skipping test for @instructure.ai/shared-configs."
90- else
91102 pnpm -F "$PKG_NAME" test
103+ else
104+ echo "Skipping build/test for @instructure.ai/shared-configs."
92105 fi
93106
94107 # Publish (use npm CLI to trigger OIDC Trusted Publishing)
95- if [ "$PKG_NAME" = "shared-configs" ]; then
96- echo "Skipping publish for @instructure.ai/shared-configs."
97- else
108+ if [ "$PKG_NAME" != "shared-configs" ]; then
98109 PKG_JSON_PATH="packages/$PKG_NAME/package.json"
99110 APP_JSON_PATH="apps/$PKG_NAME/package.json"
100111 if [ -f "$PKG_JSON_PATH" ]; then
@@ -105,21 +116,22 @@ jobs:
105116 JSON_PATH=""
106117 fi
107118
108- TARBALL=$(find ./packages/$PKG_NAME/dist -name '*.tgz' -type f | head -n 1)
119+ TARBALL=$(find " ./packages/$PKG_NAME/dist" -name '*.tgz' -type f | head -n 1)
109120 if [ -z "$TARBALL" ]; then
110121 echo "Error: No .tgz tarball found for $PKG_NAME in ./packages/$PKG_NAME/dist/"
111122 continue
112123 fi
124+
113125 if [ -n "$JSON_PATH" ]; then
114126 ACCESS_PUBLIC=$(jq -r '.publishConfig.access // empty' "$JSON_PATH")
115127 PRIVATE=$(jq -r '.private // false' "$JSON_PATH")
116128 if [ "$PRIVATE" = "true" ]; then
117- echo "Skipping publish for $PKG_NAME because it is marked private in package.json ."
129+ echo "Skipping publish for $PKG_NAME because it is marked private."
118130 elif [ "$ACCESS_PUBLIC" = "public" ]; then
119131 echo "Publishing $PKG_NAME as public via npm (OIDC)…"
120132 npm publish "$TARBALL" --access public --provenance
121133 elif [ -n "$ACCESS_PUBLIC" ] && [ "$ACCESS_PUBLIC" != "public" ]; then
122- echo "Skipping publish for $PKG_NAME because publishConfig.access is '$ACCESS_PUBLIC' (not public) ."
134+ echo "Skipping publish for $PKG_NAME because publishConfig.access is '$ACCESS_PUBLIC'."
123135 else
124136 echo "Publishing $PKG_NAME via npm (no --access public)…"
125137 npm publish "$TARBALL" --provenance
@@ -128,9 +140,11 @@ jobs:
128140 echo "package.json not found for $PKG_NAME in packages or apps, publishing without access check."
129141 npm publish "$TARBALL" --provenance
130142 fi
143+ else
144+ echo "Skipping publish for @instructure.ai/shared-configs."
131145 fi
132146
133- # Create GitHub release using gh CLI
147+ # Create GitHub release with or without asset
134148 if [ "$PKG_NAME" = "shared-configs" ]; then
135149 gh release create "$TAG" --title "$TAG" --generate-notes
136150 else
0 commit comments