1+ name : bitSign Infix Release
2+
3+ on :
4+ workflow_dispatch :
5+ inputs :
6+ release_version :
7+ description : ' Release version (e.g., v25.08.0)'
8+ required : true
9+ type : string
10+ push :
11+ branches : [ sign-with-bitsign ]
12+
13+ jobs :
14+ sign-infix-release :
15+ runs-on : ubuntu-latest
16+
17+ steps :
18+ - name : Checkout repository
19+ uses : actions/checkout@v4
20+
21+ - name : Validate release version format
22+ id : validate
23+ run : |
24+ VERSION="${{ inputs.release_version }}"
25+ echo "Validating release version: $VERSION"
26+
27+ # Check if version starts with 'v' and has proper format
28+ if ! echo "$VERSION" | grep -qE '^v[0-9]+\.[0-9]+(\.[0-9]+)?(-alpha[0-9]*|-beta[0-9]*|-rc[0-9]*)?$'; then
29+ echo "❌ Invalid version format. Expected format: vYY.MM(.PP)(-alphaN|-betaN|-rcN)"
30+ echo "Examples: v25.08.0, v25.08.0-alpha1, v25.08.0-rc1"
31+ exit 1
32+ fi
33+
34+ # Extract version without 'v' prefix for filename
35+ FILE_VERSION="${VERSION#v}"
36+ FILENAME="infix-x86_64-${FILE_VERSION}.tar.gz"
37+ RELEASE_URL="https://github.com/kernelkit/infix/releases/download/${VERSION}/${FILENAME}"
38+
39+ echo "✅ Version format valid"
40+ echo "file_version=${FILE_VERSION}" >> $GITHUB_OUTPUT
41+ echo "filename=${FILENAME}" >> $GITHUB_OUTPUT
42+ echo "release_url=${RELEASE_URL}" >> $GITHUB_OUTPUT
43+
44+ - name : Download Infix release
45+ run : |
46+ RELEASE_URL="${{ steps.validate.outputs.release_url }}"
47+ FILENAME="${{ steps.validate.outputs.filename }}"
48+
49+ echo "Downloading Infix release: $FILENAME"
50+ echo "From: $RELEASE_URL"
51+
52+ if ! curl -L "$RELEASE_URL" -o "$FILENAME" --fail --show-error --progress-bar; then
53+ echo "❌ Failed to download release file from: $RELEASE_URL"
54+ echo "Please verify that the release version exists and contains the x86_64 build."
55+ echo "You can check available releases at: https://github.com/kernelkit/infix/releases"
56+ exit 1
57+ fi
58+
59+ # Verify download
60+ if [ -f "$FILENAME" ] && [ -s "$FILENAME" ]; then
61+ FILE_SIZE=$(ls -lh "$FILENAME" | awk '{print $5}')
62+ echo "✅ Successfully downloaded: $FILENAME ($FILE_SIZE)"
63+ else
64+ echo "❌ Failed to download release file"
65+ exit 1
66+ fi
67+
68+ - name : Create signing request
69+ id : create_request
70+ run : |
71+ FILENAME="${{ steps.validate.outputs.filename }}"
72+ echo "Creating signing request for $FILENAME..."
73+
74+ # Create signing request using BitSign API
75+ RESPONSE=$(curl -s -X POST "https://portal.bitsign.se/api/v1/requests" \
76+ -H "Authorization: Bearer ${{ secrets.BITSIGN_API_KEY }}" \
77+ -F "file=@$FILENAME" \
78+ -F "key=bit42-Demo1" \
79+ -F "job=Infix-x86" \
80+ -F "parameters={\"timestamp\": true}")
81+
82+ echo "API Response: $RESPONSE"
83+
84+ # Check if request was successful
85+ if echo "$RESPONSE" | jq -e '.success == true' > /dev/null; then
86+ REQUEST_ID=$(echo "$RESPONSE" | jq -r '.requestId')
87+ echo "✅ Request created successfully with ID: $REQUEST_ID"
88+ echo "request_id=$REQUEST_ID" >> $GITHUB_OUTPUT
89+ else
90+ echo "❌ Failed to create signing request"
91+ echo "$RESPONSE" | jq -r '.error // .message // "Unknown error"'
92+ exit 1
93+ fi
94+
95+ - name : Wait for signing completion
96+ id : wait_completion
97+ run : |
98+ REQUEST_ID="${{ steps.create_request.outputs.request_id }}"
99+ echo "Waiting for signing completion for request: $REQUEST_ID"
100+
101+ # Poll status for up to 10 minutes (600 seconds) - longer timeout for larger files
102+ MAX_WAIT=600
103+ WAITED=0
104+
105+ while [ $WAITED -lt $MAX_WAIT ]; do
106+ RESPONSE=$(curl -s -X GET "https://portal.bitsign.se/api/v1/requests/$REQUEST_ID/status" \
107+ -H "Authorization: Bearer ${{ secrets.BITSIGN_API_KEY }}")
108+
109+ STATUS=$(echo "$RESPONSE" | jq -r '.status')
110+ echo "Current status: $STATUS (waited ${WAITED}s)"
111+
112+ if [ "$STATUS" = "completed" ]; then
113+ echo "✅ Signing completed successfully!"
114+ break
115+ elif [ "$STATUS" = "failed" ]; then
116+ echo "❌ Signing failed"
117+ echo "$RESPONSE" | jq -r '.error // .message // "Unknown error"'
118+ exit 1
119+ fi
120+
121+ sleep 10
122+ WAITED=$((WAITED + 10))
123+ done
124+
125+ if [ $WAITED -ge $MAX_WAIT ]; then
126+ echo "❌ Timeout: Signing did not complete within ${MAX_WAIT} seconds"
127+ exit 1
128+ fi
129+
130+ - name : Download signed file
131+ id : download_signed
132+ run : |
133+ REQUEST_ID="${{ steps.create_request.outputs.request_id }}"
134+ FILENAME="${{ steps.validate.outputs.filename }}"
135+ FILE_VERSION="${{ steps.validate.outputs.file_version }}"
136+ SIGNED_FILENAME="infix-x86_64-${FILE_VERSION}-signed.tar.gz"
137+
138+ echo "Downloading signed file for request: $REQUEST_ID"
139+ echo "Expected signed filename: $SIGNED_FILENAME"
140+
141+ # Download the signed file
142+ curl -X GET "https://portal.bitsign.se/api/v1/requests/$REQUEST_ID/download" \
143+ -H "Authorization: Bearer ${{ secrets.BITSIGN_API_KEY }}" \
144+ -o "$SIGNED_FILENAME" \
145+ --fail --show-error
146+
147+ if [ -f "$SIGNED_FILENAME" ] && [ -s "$SIGNED_FILENAME" ]; then
148+ FILE_SIZE=$(ls -lh "$SIGNED_FILENAME" | awk '{print $5}')
149+ echo "Successfully downloaded signed file: $SIGNED_FILENAME ($FILE_SIZE)"
150+ echo "signed_filename=$SIGNED_FILENAME" >> $GITHUB_OUTPUT
151+ else
152+ echo "Failed to download signed file"
153+ exit 1
154+ fi
155+
156+ - name : Upload signed artifacts
157+ uses : actions/upload-artifact@v4
158+ with :
159+ name : signed-infix-${{ steps.validate.outputs.file_version }}
160+ path : |
161+ ${{ steps.validate.outputs.filename }}
162+ ${{ steps.download_signed.outputs.signed_filename }}
163+ retention-days : 90
164+
165+ - name : Summary
166+ run : |
167+ cat >> $GITHUB_STEP_SUMMARY << 'EOF'
168+ # bitSign Infix Release Signing Complete
169+
170+ The Infix release has been successfully signed using the bitSign API.
171+
172+ ## Process Overview
173+
174+ 1. **Release Download** - Downloaded specified Infix release from GitHub
175+ 2. **Signing Request** - Created signing request via bitSign API
176+ 3. **Approval Process** - Trusted signers received notification and approved with 2FA
177+ 4. **bitSign Processing** - Backend securely signed the release file
178+ 5. **Download & Store** - Retrieved signed result and stored as artifacts
179+
180+ ## Signing Details
181+
182+ | Property | Value |
183+ |----------|-------|
184+ | 📦 **Original File** | `${{ steps.validate.outputs.filename }}` |
185+ | ✍️ **Signed File** | `${{ steps.download_signed.outputs.signed_filename }}` |
186+ | 🔑 **Signing Key** | `bit42-Demo1` |
187+ | ⚙️ **Job Type** | `Infix-x86` |
188+ | 🆔 **Request ID** | `${{ steps.create_request.outputs.request_id }}` |
189+ | 📋 **Release Version** | `${{ inputs.release_version }}` |
190+ | 🌐 **API Endpoint** | `portal.bitsign.se` |
191+
192+ ## Download Files
193+
194+ > **Both the original release file and signed version are available as a workflow artifact:**
195+ > **`signed-infix-${{ steps.validate.outputs.file_version }}`**
196+ >
197+ > The artifact contains both `${{ steps.validate.outputs.filename }}` and `${{ steps.download_signed.outputs.signed_filename }}` files.
198+
199+ ---
200+
201+ **Next Steps:** The signed release can now be distributed with cryptographic verification of authenticity.
202+ EOF
0 commit comments