99 - " v[0-9]+.[0-9]+.[0-9]+"
1010 - " v[0-9]+.[0-9]+.[0-9]+-*"
1111
12+ # ---- Global permissions for Trusted Publishing & attestations ----
13+ # id-token:write is required for OIDC (npm trusted publishing, keyless attestations)
14+ # packages:write for GHCR; attestations:write for GitHub artifact attestations (optional but recommended)
15+ permissions :
16+ contents : read
17+ packages : write
18+ id-token : write
19+ attestations : write
20+
1221env :
1322 IMAGE_NAME : ${{ github.repository_owner }}/fabric-nodeenv
1423
1524jobs :
1625 test :
1726 uses : ./.github/workflows/test.yaml
1827
28+ # =============== npm (Trusted Publisher via OIDC) ==================
29+ # Pre-req (one-time): In npm, enable "Trusted publishing" for the package
30+ # and link this repo/workflow. Then you no longer need NPM_TOKEN. [oai_citation:0‡npm Docs](https://docs.npmjs.com/trusted-publishers/?utm_source=chatgpt.com)
1931 publishnpm :
2032 runs-on : ubuntu-24.04
2133 needs : test
34+ permissions :
35+ contents : read
36+ id-token : write
2237 steps :
2338 - uses : actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
2439 with :
@@ -28,21 +43,24 @@ jobs:
2843 with :
2944 name : node-tgzs
3045 path : build/
31- - run : |
46+ - name : Publish packages with provenance (OIDC)
47+ # No NODE_AUTH_TOKEN needed when Trusted Publishing is enabled.
48+ # --provenance tells npm to attach SLSA provenance to the package. [oai_citation:1‡The GitHub Blog](https://github.blog/security/supply-chain-security/introducing-npm-package-provenance/?utm_source=chatgpt.com)
49+ run : |
3250 set -xev
3351 ls -lart build/
3452 cd build
35- find . -type f -name 'fabric-*.tgz' -exec npm publish {} \;
36- env:
37- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
53+ find . -type f -name 'fabric-*.tgz' -print0 | xargs -0 -I{} npm publish {} --provenance --access public
3854
55+ # ========= Build & push per-arch images (with provenance/SBOM) =========
3956 docker-build-push :
40- name : Push Docker image
57+ name : Build & Push Docker image (per-arch)
4158 needs : test
4259 runs-on : ${{ matrix.arch.runner }}
4360 permissions :
4461 contents : read
45- packages : write
62+ packages : write # for ghcr.io
63+ id-token : write # for provenance/attestations
4664 strategy :
4765 fail-fast : false
4866 matrix :
@@ -53,50 +71,68 @@ jobs:
5371 runner : ubuntu-24.04-arm
5472 steps :
5573 - uses : actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
74+
5675 - name : Get commit timestamp
5776 run : echo "SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct)" >> "${GITHUB_ENV}"
58- - name : Login to GitHub Container Registry
77+
78+ # ---- GHCR login via GITHUB_TOKEN (already short-lived/trusted) ----
79+ - name : Login to GitHub Container Registry (ghcr.io)
5980 uses : docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
6081 with :
6182 registry : ghcr.io
6283 username : ${{ github.actor }}
6384 password : ${{ secrets.GITHUB_TOKEN }}
85+
86+ # ---- Optional: Docker Hub login (kept for now) ----
87+ # If your Docker Hub org enables its own trusted/OIDC flow later, you can
88+ # replace this with that method; until then PAT is required. [oai_citation:2‡Docker Documentation](https://docs.docker.com/docker-hub/image-library/trusted-content/?utm_source=chatgpt.com)
6489 - name : Login to Docker Hub
90+ if : ${{ secrets.DOCKERHUB_USERNAME && secrets.DOCKERHUB_TOKEN }}
6591 uses : docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
6692 with :
6793 registry : docker.io
6894 username : ${{ secrets.DOCKERHUB_USERNAME }}
6995 password : ${{ secrets.DOCKERHUB_TOKEN }}
96+
7097 - name : Set up Docker Buildx
7198 uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
72- - name : Build image
99+
100+ - name : Build image (per-arch) with provenance + SBOM
73101 id : build
74102 uses : docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
75103 with :
76104 file : docker/fabric-nodeenv/Dockerfile
77105 context : docker/fabric-nodeenv
106+ platforms : ${{ matrix.arch.platform }}
107+ # Generate and attach provenance/SBOM at build time. [oai_citation:3‡Docker Documentation](https://docs.docker.com/build/metadata/attestations/slsa-provenance/?utm_source=chatgpt.com)
108+ provenance : true
109+ sbom : true
78110 outputs : type=registry,"name=${{ format('ghcr.io/{0},docker.io/{0}', env.IMAGE_NAME) }}",push-by-digest=true,name-canonical=true
79111 env :
80112 SOURCE_DATE_EPOCH : ${{ env.SOURCE_DATE_EPOCH }}
113+
81114 - name : Export digest
82115 run : |
83116 mkdir -p ${{ runner.temp }}/digests
84117 digest="${{ steps.build.outputs.digest }}"
85118 touch "${{ runner.temp }}/digests/${digest#sha256:}"
119+
86120 - name : Upload digest
87121 uses : actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
88122 with :
89123 name : digest-${{ matrix.arch.platform }}
90124 path : ${{ runner.temp }}/digests/*
91125 if-no-files-found : error
92126
127+ # =============== Manifest + tags publishing ==================
93128 docker-meta :
94129 needs : docker-build-push
95130 name : Publish Docker metadata
96131 runs-on : ubuntu-latest
97132 permissions :
98133 contents : read
99134 packages : write
135+ id-token : write
100136 strategy :
101137 fail-fast : false
102138 matrix :
@@ -110,12 +146,14 @@ jobs:
110146 path : ${{ runner.temp }}/digests
111147 pattern : digest-*
112148 merge-multiple : true
149+
113150 - name : Login to ${{ matrix.registry }}
114151 uses : docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0
115152 with :
116153 registry : ${{ matrix.registry }}
117154 username : ${{ matrix.registry == 'docker.io' && secrets.DOCKERHUB_USERNAME || github.actor }}
118155 password : ${{ matrix.registry == 'docker.io' && secrets.DOCKERHUB_TOKEN || secrets.GITHUB_TOKEN }}
156+
119157 - name : Docker metadata
120158 id : meta
121159 uses : docker/metadata-action@c1e51972afc2121e065aed6d45c65596fe445f3f # v5.8.0
@@ -125,12 +163,15 @@ jobs:
125163 type=semver,pattern={{version}}
126164 type=semver,pattern={{major}}.{{minor}}
127165 type=semver,pattern={{major}}.{{minor}}.{{patch}}
166+
128167 - name : Set up Docker Buildx
129168 uses : docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1
169+
130170 - name : Create and push manifest list
131171 working-directory : ${{ runner.temp }}/digests
132172 run : |
133173 docker buildx imagetools create $(jq -cr '.tags | map("--tag " + .) | join(" ")' <<< "${DOCKER_METADATA_OUTPUT_JSON}") \
134174 $(printf '${{ matrix.registry }}/${{ env.IMAGE_NAME }}@sha256:%s ' *)
175+
135176 - name : Inspect image
136177 run : docker buildx imagetools inspect '${{ matrix.registry }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}'
0 commit comments