Skip to content

Commit a927e63

Browse files
Suresh MandalapuSuresh Mandalapu
authored andcommitted
docker publish changes
1 parent 792cee0 commit a927e63

2 files changed

Lines changed: 53 additions & 10 deletions

File tree

.github/workflows/docker-publish.yml

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
CLEANCLOUD_VERSION="${{ steps.version.outputs.CLEANCLOUD_VERSION }}"
2727
echo "Waiting for cleancloud==${CLEANCLOUD_VERSION} to appear on PyPI..."
2828
for i in $(seq 1 20); do
29-
curl -sf "https://pypi.org/pypi/cleancloud/${CLEANCLOUD_VERSION}/json" > /dev/null && echo "Found on PyPI" && exit 0
29+
curl -sf --retry 3 --retry-delay 5 "https://pypi.org/pypi/cleancloud/${CLEANCLOUD_VERSION}/json" > /dev/null && echo "Found on PyPI" && exit 0
3030
echo "Not yet available (attempt $i/20), retrying in 30s..."
3131
sleep 30
3232
done
@@ -52,14 +52,13 @@ jobs:
5252
tags: |
5353
type=semver,pattern={{version}}
5454
type=semver,pattern=v{{version}}
55-
type=semver,pattern={{major}}.{{minor}}
56-
type=semver,pattern={{major}}
57-
type=raw,value=latest
55+
type=raw,value=latest,enable=${{ !github.event.release.prerelease }}
5856
labels: |
59-
org.opencontainers.image.description=Read-only cloud hygiene scanner for AWS and Azure
57+
org.opencontainers.image.description=Read-only cloud hygiene scanner for AWS, Azure, and GCP
6058
org.opencontainers.image.licenses=MIT
6159
6260
- name: Build and push
61+
id: build
6362
uses: docker/build-push-action@v6
6463
with:
6564
context: .
@@ -71,15 +70,28 @@ jobs:
7170
labels: ${{ steps.meta.outputs.labels }}
7271
cache-from: type=gha
7372
cache-to: type=gha,mode=max
73+
provenance: true
74+
sbom: true
75+
76+
- name: Log image digest
77+
run: echo "Image digest ${{ steps.build.outputs.digest }}"
7478

7579
- name: Update release notes with Docker info
7680
uses: actions/github-script@v7
7781
with:
7882
script: |
7983
const version = '${{ steps.version.outputs.CLEANCLOUD_VERSION }}';
84+
const digest = '${{ steps.build.outputs.digest }}';
8085
const currentBody = context.payload.release.body || '';
86+
87+
// Idempotent: skip if Docker section already present (workflow rerun guard)
88+
if (currentBody.includes('🐳 **Docker Image**')) {
89+
console.log('Docker section already present, skipping update.');
90+
return;
91+
}
92+
8193
const safeBody = currentBody.endsWith('\n') ? currentBody : currentBody + '\n';
82-
const dockerInfo = `\n🐳 **Docker Image**\n\n\`\`\`bash\n# AWS\ndocker run --rm -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_REGION getcleancloud/cleancloud scan --provider aws --all-regions\n\n# Azure\ndocker run --rm -e AZURE_CLIENT_ID -e AZURE_TENANT_ID -e AZURE_SUBSCRIPTION_ID -e AZURE_FEDERATED_TOKEN_FILE -v "\${AZURE_FEDERATED_TOKEN_FILE}:\${AZURE_FEDERATED_TOKEN_FILE}:ro" getcleancloud/cleancloud scan --provider azure\n\`\`\`\n\n📦 Pull: \`docker pull getcleancloud/cleancloud:${version}\`\n🔗 Docker Hub: https://hub.docker.com/r/getcleancloud/cleancloud`;
94+
const dockerInfo = `\n🐳 **Docker Image**\n\n\`\`\`bash\n# AWS\ndocker run --rm -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_REGION getcleancloud/cleancloud scan --provider aws --all-regions\n\n# Azure\ndocker run --rm -e AZURE_CLIENT_ID -e AZURE_TENANT_ID -e AZURE_SUBSCRIPTION_ID -e AZURE_FEDERATED_TOKEN_FILE -v "\${AZURE_FEDERATED_TOKEN_FILE}:\${AZURE_FEDERATED_TOKEN_FILE}:ro" getcleancloud/cleancloud scan --provider azure\n\n# GCP (WIF or service account key)\ndocker run --rm -e GOOGLE_APPLICATION_CREDENTIALS=/gcp-creds.json -v "\${GOOGLE_APPLICATION_CREDENTIALS}:/gcp-creds.json:ro" getcleancloud/cleancloud scan --provider gcp --all-projects\n\`\`\`\n\n📦 Pull: \`docker pull getcleancloud/cleancloud:${version}\`\n🔗 Docker Hub: https://hub.docker.com/r/getcleancloud/cleancloud\n🔏 Digest: \`${digest}\``;
8395
8496
await github.rest.repos.updateRelease({
8597
owner: context.repo.owner,

docs/ci.md

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -240,15 +240,46 @@ jobs:
240240

241241
> Azure Workload Identity writes an OIDC token to a temp file on the runner. The `-v` mount makes that file accessible inside the container.
242242

243+
### GCP
244+
245+
GCP Application Default Credentials are resolved via a file-based mechanism. In GitHub Actions with Workload Identity Federation, `google-github-actions/auth@v2` exchanges the OIDC token and writes a short-lived credentials file to the runner filesystem, then sets `GOOGLE_APPLICATION_CREDENTIALS` to point to it. That file must be mounted into the container.
246+
247+
```yaml
248+
jobs:
249+
cleancloud:
250+
runs-on: ubuntu-latest
251+
permissions:
252+
id-token: write
253+
contents: read
254+
steps:
255+
- uses: google-github-actions/auth@v2
256+
with:
257+
workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
258+
service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}
259+
260+
- name: Run CleanCloud
261+
run: |
262+
test -f "$GOOGLE_APPLICATION_CREDENTIALS" || exit 1
263+
echo "Using GCP credentials at: $GOOGLE_APPLICATION_CREDENTIALS"
264+
265+
docker run --rm \
266+
-e GOOGLE_APPLICATION_CREDENTIALS=/gcp-creds.json \
267+
-v "$GOOGLE_APPLICATION_CREDENTIALS:/gcp-creds.json:ro" \
268+
getcleancloud/cleancloud scan \
269+
--provider gcp \
270+
--all-projects \
271+
--fail-on-confidence HIGH \
272+
--fail-on-cost 100
273+
```
274+
275+
> The credentials file is short-lived and mounted read-only — no long-lived keys are exposed. The `test -f` guard catches a silent auth failure before Docker attempts the mount.
276+
243277
### Pinning to a specific version
244278

245279
```yaml
246280
# Pin to exact version — safest for production pipelines
247281
getcleancloud/cleancloud:1.9.0
248282
249-
# Pin to minor — gets patch fixes automatically
250-
getcleancloud/cleancloud:1.9
251-
252283
# Always latest — simplest, least predictable
253284
getcleancloud/cleancloud:latest
254285
```
@@ -667,7 +698,7 @@ cleancloud scan \
667698

668699
**JSON is the recommended format for programmatic processing** as it contains complete data including evidence and detailed metadata.
669700

670-
The JSON output follows a versioned schema (see `schemas/output-v1.0.0.json`) and varies slightly between providers to accommodate their different organizational models (AWS regions vs Azure subscriptions).
701+
The JSON output follows a versioned schema (see `schemas/output-v1.2.0.json`) and varies slightly between providers to accommodate their different organizational models (AWS regions vs Azure subscriptions).
671702

672703
**AWS Schema Example:**
673704
```json

0 commit comments

Comments
 (0)