Skip to content

Commit 07d1686

Browse files
authored
Introducing code signing, build provenance attestation, and persisting artifacts to GCS (#873)
1 parent b49f606 commit 07d1686

File tree

1 file changed

+127
-8
lines changed

1 file changed

+127
-8
lines changed

.github/workflows/deno.yml

Lines changed: 127 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Deno Workflow
1+
name: Deno Workflow
22

33
on:
44
push:
@@ -25,13 +25,13 @@ jobs:
2525
~/.deno
2626
~/.cache/deno
2727
key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.json') }}
28-
- name: Install dependencies
28+
- name: Install dependencies
2929
# Errors if `deno.lock` file was not
3030
# committed with the current change.
3131
run: deno install --frozen=true
32-
- name: Check
32+
- name: Check
3333
run: deno task check
34-
- name: Lint
34+
- name: Lint
3535
run: deno lint
3636
# For deno-web-test browser tests
3737
# https://github.com/lino-levan/astral/blob/f5ef833b2c5bde3783564a6b925073d5d46bb4b8/README.md#no-usable-sandbox-with-user-namespace-cloning-enabled
@@ -43,31 +43,144 @@ jobs:
4343
build-artifact:
4444
name: "Build Artifact"
4545
runs-on: ubuntu-latest
46-
needs: ['workspace-tests']
46+
needs: ["workspace-tests"]
47+
environment: production
48+
permissions:
49+
id-token: write
50+
contents: read
51+
actions: read
52+
attestations: write
4753
steps:
4854
- uses: actions/checkout@v4
55+
4956
- name: Setup Deno
5057
uses: denoland/setup-deno@v2
5158
with:
5259
deno-version: "2.2.2"
60+
5361
- name: Cache dependencies
5462
uses: actions/cache@v3
5563
with:
5664
path: |
5765
~/.deno
5866
~/.cache/deno
5967
key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.json') }}
60-
- name: Build artifact
68+
69+
- name: Build artifact
6170
run: deno task build-artifact
71+
72+
- name: Sign and package for main
73+
if: github.ref == 'refs/heads/main'
74+
run: |
75+
openssl dgst -sha256 -sign <(echo "${{ secrets.ARTIFACT_SIGNING_KEY }}") -out ./artifact.sig ./artifact
76+
mkdir -p release
77+
tar -czf release/${{ github.sha }}.tar.gz ./artifact ./artifact.sig
78+
79+
- name: Generate hashes for main
80+
if: github.ref == 'refs/heads/main'
81+
id: hash
82+
run: |
83+
sha256sum release/${{ github.sha }}.tar.gz > release/${{ github.sha }}.hash.txt
84+
ARTIFACT_HASH=$(cat release/${{ github.sha }}.hash.txt | awk '{print $1}')
85+
echo "Hash value: $ARTIFACT_HASH"
86+
echo "hash=$ARTIFACT_HASH" >> $GITHUB_OUTPUT
87+
88+
- name: Generate binary hash for main
89+
if: github.ref == 'refs/heads/main'
90+
id: binary_hash
91+
run: |
92+
sha256sum ./artifact > binary.hash.txt
93+
BINARY_HASH=$(cat binary.hash.txt | awk '{print $1}')
94+
echo "Binary hash value: $BINARY_HASH"
95+
echo "binary_hash=$BINARY_HASH" >> $GITHUB_OUTPUT
96+
97+
- name: Generate binary attestation for main
98+
if: github.ref == 'refs/heads/main'
99+
id: attest_binary
100+
uses: actions/attest-build-provenance@v1
101+
with:
102+
subject-name: ./artifact
103+
subject-digest: sha256:${{ steps.binary_hash.outputs.binary_hash }}
104+
105+
- name: Upload binary attestation for main
106+
if: github.ref == 'refs/heads/main'
107+
uses: actions/upload-artifact@v4
108+
with:
109+
name: attest_binary
110+
if-no-files-found: error
111+
path: ${{ steps.attest_binary.outputs.bundle-path }}
112+
113+
- name: Generate tarball attestation for main
114+
if: github.ref == 'refs/heads/main'
115+
id: attest_tarball
116+
uses: actions/attest-build-provenance@v1
117+
with:
118+
subject-name: https://storage.cloud.google.com/commontools-build-artifacts/workspace-artifacts/${{ github.sha }}.tar.gz
119+
subject-digest: sha256:${{ steps.hash.outputs.hash }}
120+
121+
- name: Upload tarball attestation for main
122+
if: github.ref == 'refs/heads/main'
123+
uses: actions/upload-artifact@v4
124+
with:
125+
name: attest_tarball
126+
if-no-files-found: error
127+
path: ${{ steps.attest_tarball.outputs.bundle-path }}
128+
129+
- name: Verify tarball attestation for main
130+
if: github.ref == 'refs/heads/main'
131+
env:
132+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
133+
run: |
134+
echo "::group::Tarball attestation details"
135+
gh attestation verify release/${{ github.sha }}.tar.gz -R ${{ github.repository }} --format json | jq
136+
echo "::endgroup::"
137+
if [ $? -eq 0 ]; then
138+
echo -e "\033[32m✓ Tarball attestation verified successfully\033[0m"
139+
else
140+
echo -e "\033[31m✗ Tarball attestation verification failed\033[0m"
141+
exit 1
142+
fi
143+
144+
- name: Verify binary attestation for main
145+
if: github.ref == 'refs/heads/main'
146+
env:
147+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
148+
run: |
149+
echo "::group::Binary attestation details"
150+
gh attestation verify ./artifact -R ${{ github.repository }} --format json | jq
151+
echo "::endgroup::"
152+
if [ $? -eq 0 ]; then
153+
echo -e "\033[32m✓ Binary attestation verified successfully\033[0m"
154+
else
155+
echo -e "\033[31m✗ Binary attestation verification failed\033[0m"
156+
exit 1
157+
fi
158+
159+
- name: Authenticate to Google Cloud for main
160+
if: github.ref == 'refs/heads/main'
161+
uses: google-github-actions/auth@v1
162+
with:
163+
credentials_json: ${{ secrets.GCP_SA_KEY }}
164+
165+
- name: Setup Google Cloud SDK for main
166+
if: github.ref == 'refs/heads/main'
167+
uses: google-github-actions/setup-gcloud@v1
168+
169+
- name: Upload to GCS for main
170+
if: github.ref == 'refs/heads/main'
171+
run: |
172+
gsutil cp release/${{ github.sha }}.tar.gz gs://commontools-build-artifacts/workspace-artifacts/
173+
gsutil cp release/${{ github.sha }}.hash.txt gs://commontools-build-artifacts/workspace-artifacts/
174+
62175
- uses: actions/upload-artifact@v4
63176
with:
64177
name: common-artifact
65178
path: ./artifact
66-
179+
67180
integration-test:
68181
name: "Integration Tests"
69182
runs-on: ubuntu-latest
70-
needs: ['build-artifact']
183+
needs: ["build-artifact"]
71184
environment: production
72185
services:
73186
redis:
@@ -81,28 +194,34 @@ jobs:
81194
--health-retries 5
82195
steps:
83196
- uses: actions/checkout@v4
197+
84198
- name: Setup Deno
85199
uses: denoland/setup-deno@v2
86200
with:
87201
deno-version: "2.2.2"
202+
88203
- name: Cache dependencies
89204
uses: actions/cache@v3
90205
with:
91206
path: |
92207
~/.deno
93208
~/.cache/deno
94209
key: ${{ runner.os }}-deno-${{ hashFiles('**/deno.json') }}
210+
95211
- uses: actions/download-artifact@v4
212+
96213
- name: Run Compiled Toolshed
97214
run: |
98215
chmod +x ./common-artifact/artifact
99216
CTTS_AI_LLM_ANTHROPIC_API_KEY=fake \
100217
CACHE_DIR=${GITHUB_WORKSPACE}/jumble/integration/cache \
101218
./common-artifact/artifact &
219+
102220
# For Astral
103221
# https://github.com/lino-levan/astral/blob/f5ef833b2c5bde3783564a6b925073d5d46bb4b8/README.md#no-usable-sandbox-with-user-namespace-cloning-enabled
104222
- name: Disable AppArmor
105223
run: echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns
224+
106225
- name: Run Integration
107226
working-directory: jumble
108227
run: |

0 commit comments

Comments
 (0)