Skip to content

Commit 56b09b1

Browse files
harshita-guptaclaudeskeggse
authored
workflows: swap softprops for gh CLI, add CloudFront reachability check, remove --acl (#18)
* workflows: swap softprops for gh CLI, add CloudFront reachability check, remove --acl Three follow-up corrections to PR #17: 1. Remove `--acl public-read` from `aws s3 cp`. The bucket has `disable_confusing_acls = true` (BucketOwnerEnforced), which disables ACLs entirely. `BlockPublicAcls` + `IgnorePublicAcls` provide additional coverage. The ACL flag is silently ignored. The IAM role (`S3_ACCESS_MODE.PUT`) also doesn't grant `PutObjectAcl`. Reads go via CloudFront OAC, not public-S3. 2. Replace `softprops/action-gh-release` with GitHub's first-party `gh` CLI. `gh release upload` is pre-installed on GitHub-hosted runners, removes a third-party (single-maintainer) supply-chain dependency, and behaves equivalently with `--clobber`. 3. Add a post-upload CloudFront reachability check (`curl -fI`). If the CloudFront path_patterns allowlist doesn't include the key's prefix, Mac Bazel builds will silently 403. Failing the workflow here surfaces the issue before consumers hit it. S3 path stays `node-gyp/*` (this PR no longer changes it — see codez PR #390222 which adds `node-gyp/*` to CloudFront's path_patterns in system_packages.tf). Action pinning: tag-pinned per codez convention (100% of codez workflows use tags, not SHAs). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Update .github/workflows/build-node-packages.yml Co-authored-by: Eli Skeggs <1348991+skeggse@users.noreply.github.com> * workflows: hoist matrix values to job-level env, drop expression substitution in run: blocks Eli's review flagged `${{ matrix.arch }}` in a run: block as an injectable pattern even though the matrix values are hardcoded and not truly exploitable. Apply the pattern consistently across the whole workflow: - Hoist PLATFORM, ARCH, BAZEL_ARCH, REPO to job-level env so each step can reference them as shell variables ($ARCH etc.) rather than GitHub Actions expressions (${{ matrix.arch }}). Job-level env evaluates matrix context since the job is instantiated per matrix combination, so this DRYs up the per-step env blocks. - Rewrite every `run:` block to reference the job-level env vars. No more `${{ ... }}` expressions inside shell scripts. - Secret references (GITHUB_TOKEN) remain step-scoped per least-privilege. - Minor cleanup: collapse three separate `echo ... >> $GITHUB_ENV` lines into a single `{ ...; } >> "$GITHUB_ENV"` block. Addresses Eli's inline comment on line 114 of the pre-hoist file. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Harshita Gupta <harshita-gupta@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Eli Skeggs <1348991+skeggse@users.noreply.github.com>
1 parent 104256b commit 56b09b1

2 files changed

Lines changed: 64 additions & 23 deletions

File tree

.github/workflows/build-node-packages.yml

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,29 @@ jobs:
3030

3131
env:
3232
NODE_VERSION: v22.21.1
33+
PLATFORM: ${{ matrix.platform }}
34+
ARCH: ${{ matrix.arch }}
35+
BAZEL_ARCH: ${{ matrix.bazel_arch }}
36+
REPO: ${{ github.repository }}
3337

3438
steps:
3539
- name: Checkout repository
3640
uses: actions/checkout@v3
3741

3842
- name: Debug Matrix Values
3943
run: |
40-
echo "Matrix platform: ${{ matrix.platform }}"
41-
echo "Matrix arch: ${{ matrix.arch }}"
44+
echo "Matrix platform: $PLATFORM"
45+
echo "Matrix arch: $ARCH"
4246
4347
- name: Download Node archive
44-
run: |
45-
gh release download node-${{ env.NODE_VERSION }}-release \
46-
--repo asana/node \
47-
--pattern "node-${{ env.NODE_VERSION }}-${{ matrix.platform }}-${{ matrix.arch }}-LATEST.tar.xz"
48-
mv node-${{ env.NODE_VERSION }}-${{ matrix.platform }}-${{ matrix.arch }}-LATEST.tar.xz node.tar.xz
4948
env:
5049
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
run: |
51+
ASSET="node-${NODE_VERSION}-${PLATFORM}-${ARCH}-LATEST.tar.xz"
52+
gh release download "node-${NODE_VERSION}-release" \
53+
--repo asana/node \
54+
--pattern "$ASSET"
55+
mv "$ASSET" node.tar.xz
5156
5257
- name: Execute the Dockerfile
5358
run: |
@@ -70,16 +75,20 @@ jobs:
7075
mv node_modules/cld ./cld@2.9.1/node_modules/
7176
mv node_modules/unix-dgram ./unix-dgram@2.0.6/node_modules/
7277
mv "node_modules/@datadog/pprof" "./@datadog+pprof@5.8.0/node_modules/@datadog/"
73-
tar --hard-dereference -cvzf packages_${{matrix.arch}}.tar.gz bcrypt@5.1.0 cld@2.9.1 unix-dgram@2.0.6 "@datadog+pprof@5.8.0"
78+
tar --hard-dereference -cvzf "packages_${ARCH}.tar.gz" bcrypt@5.1.0 cld@2.9.1 unix-dgram@2.0.6 "@datadog+pprof@5.8.0"
7479
7580
- name: Upload archive to release
76-
uses: softprops/action-gh-release@v1
77-
with:
78-
name: node-${{ env.NODE_VERSION }}-LATEST
79-
tag_name: node-${{ env.NODE_VERSION }}-release
80-
files: packages_${{matrix.arch}}.tar.gz
81+
# Use `gh release upload` (first-party GitHub CLI, pre-installed on runners)
82+
# instead of softprops/action-gh-release (one-maintainer third-party action).
83+
# Behavior: --clobber overwrites an existing asset with the same name, matching
84+
# softprops's default. The release must already exist (created by build-node.yml).
8185
env:
8286
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
87+
run: |
88+
gh release upload "node-${NODE_VERSION}-release" \
89+
"packages_${ARCH}.tar.gz" \
90+
--clobber \
91+
--repo "$REPO"
8392
8493
# S3 upload is restricted to the protected main branch only. The IAM role
8594
# (push_node_gyp_packages) trusts only refs/heads/main via OIDC. To upload
@@ -94,14 +103,45 @@ jobs:
94103
- name: Upload packages to S3
95104
if: github.ref == 'refs/heads/main'
96105
run: |
97-
NODE_MAJOR=$(echo "${{ env.NODE_VERSION }}" | sed 's/^v//' | cut -d. -f1)
98-
SHA256=$(sha256sum "packages_${{ matrix.arch }}.tar.gz" | awk '{print $1}')
106+
# Upload to s3://asana-oss-cache/node-gyp/... (CloudFront path_patterns entry
107+
# added in codez PR #390222 — that must be merged + applied via Spacelift
108+
# before this workflow can successfully publish fetchable objects).
109+
#
110+
# No --acl public-read: the bucket has BucketOwnerEnforced
111+
# (disable_confusing_acls = true), which disables ACLs entirely.
112+
# BlockPublicAcls + IgnorePublicAcls provide additional coverage.
113+
# Reads come via CloudFront OAC.
114+
NODE_MAJOR=$(echo "$NODE_VERSION" | sed 's/^v//' | cut -d. -f1)
115+
SHA256=$(sha256sum "packages_${ARCH}.tar.gz" | awk '{print $1}')
99116
SHORT_HASH=${SHA256:0:8}
100-
S3_KEY="node-gyp/packages_${{ matrix.bazel_arch }}_node${NODE_MAJOR}-${SHORT_HASH}.tar.gz"
101-
echo "Uploading packages_${{ matrix.arch }}.tar.gz to s3://asana-oss-cache/${S3_KEY}"
102-
aws s3 cp "packages_${{ matrix.arch }}.tar.gz" "s3://asana-oss-cache/${S3_KEY}" --acl public-read
117+
S3_KEY="node-gyp/packages_${BAZEL_ARCH}_node${NODE_MAJOR}-${SHORT_HASH}.tar.gz"
118+
echo "Uploading packages_${ARCH}.tar.gz to s3://asana-oss-cache/$S3_KEY"
119+
aws s3 cp "packages_${ARCH}.tar.gz" "s3://asana-oss-cache/$S3_KEY"
120+
{
121+
echo "S3_KEY=$S3_KEY"
122+
echo "SHA256=$SHA256"
123+
echo "NODE_MAJOR=$NODE_MAJOR"
124+
} >> "$GITHUB_ENV"
125+
126+
- name: Verify upload is reachable via CloudFront
127+
if: github.ref == 'refs/heads/main'
128+
run: |
129+
# Mac Bazel builds rewrite asana-oss-cache.s3.us-east-1.amazonaws.com/*
130+
# to asana-oss-cache.asana.biz/* (CloudFront). If the S3 key prefix isn't
131+
# allowlisted in CloudFront's path_patterns, Bazel fetches will 403.
132+
# Fail fast here rather than after someone tries to build.
133+
URL="https://asana-oss-cache.asana.biz/$S3_KEY"
134+
echo "Checking $URL"
135+
if ! curl -fsSI "$URL"; then
136+
echo "CloudFront returned an error for $URL. Check path_patterns in system_packages.tf."
137+
exit 1
138+
fi
139+
140+
- name: Print tools_repositories.bzl stanza
141+
if: github.ref == 'refs/heads/main'
142+
run: |
103143
echo ""
104144
echo "=== Update tools_repositories.bzl in codez ==="
105-
echo " name = \"node_gyp_packages_${{ matrix.bazel_arch }}_node${NODE_MAJOR}\","
106-
echo " urls = [\"https://asana-oss-cache.s3.us-east-1.amazonaws.com/${S3_KEY}\"],"
107-
echo " sha256 = \"${SHA256}\","
145+
echo " name = \"node_gyp_packages_${BAZEL_ARCH}_node${NODE_MAJOR}\","
146+
echo " urls = [\"https://asana-oss-cache.s3.us-east-1.amazonaws.com/$S3_KEY\"],"
147+
echo " sha256 = \"$SHA256\","

stage_for_s3.bash

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ gh release download -p "*.xz"
1616
echo ""
1717
echo "=== Native packages (node-gyp) ==="
1818
echo "These are uploaded to s3://asana-oss-cache/node-gyp/ by the build-node-packages.yml workflow"
19-
echo "with content-hashed S3 keys. Each build produces an immutable artifact."
19+
echo "(triggered via workflow_dispatch from main) with content-hashed S3 keys."
20+
echo "Each build produces an immutable artifact."
2021
for pkg in packages_*.tar.gz; do
2122
if [ -f "$pkg" ]; then
2223
echo " $pkg: sha256=$(sha256sum "$pkg" | awk '{print $1}')"
2324
rm "$pkg"
2425
fi
2526
done
26-
echo "No manual action needed for packages — they are already in S3."
27+
echo "No manual action needed for packages if you've already dispatched build-node-packages.yml from main."
2728
echo ""
2829

2930
curl "https://asana-oss-cache.s3.us-east-1.amazonaws.com/node-fibers/fibers-5.0.4.pc.tgz" --output fibers-5.0.4.tar.gz

0 commit comments

Comments
 (0)