Skip to content

Build and deploy with evidence #60

Build and deploy with evidence

Build and deploy with evidence #60

name: Build and deploy with evidence
on:
[workflow_dispatch]
permissions:
id-token: write
contents: read
attestations: write
jobs:
docker-build-with-evidence:
runs-on: ubuntu-latest
outputs:
image_name: ${{ steps.docker-build.outputs.full_image_name }}
env:
REPO_NAME: evidence-demo-docker-dev
# JFROG_CLI_LOG_LEVEL: DEBUG
steps:
- name: Install jfrog cli
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- uses: actions/checkout@v4
- name: Log in to Artifactory Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ vars.ARTIFACTORY_URL }}
username: ${{ secrets.JF_USER }}
password: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64
install: true
- name: Setup Cosign
uses: sigstore/cosign-installer@main
- name: Build Docker image
id: docker-build
run: |
URL=$(echo ${{ vars.ARTIFACTORY_URL }} | sed 's|^https://||')
REPO_URL=${URL}/${REPO_NAME}
docker build --build-arg REPO_URL=${REPO_URL} -f Dockerfile . \
--tag ${REPO_URL}/example-project-app:${{ github.run_number }} \
--output=type=image --platform linux/amd64 --metadata-file=build-metadata --push
jfrog rt build-docker-create ${REPO_NAME} --image-file build-metadata --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }}
DIGEST=$(docker buildx imagetools inspect --raw ${REPO_URL}/example-project-app:${{ github.run_number }} | jq -r '.manifests[0].digest')
echo "digest=$DIGEST" >> $GITHUB_OUTPUT
echo "image_name=${REPO_URL}/example-project-app" >> $GITHUB_OUTPUT
echo "full_image_name=example-project-app:${{ github.run_number }}@$DIGEST" >> $GITHUB_OUTPUT
- name: Sign docker image
env:
TAGS: ${{ steps.docker_meta.outputs.tags }}
COSIGN_PRIVATE_KEY: ${{ secrets.COSIGN_KEY }}
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
DIGEST: ${{ steps.build-and-push.outputs.digest }}
run: |
URL=$(echo ${{ vars.ARTIFACTORY_URL }} | sed 's|^https://||')
REPO_URL=${URL}/${REPO_NAME}
cosign sign --yes --key env://COSIGN_PRIVATE_KEY ${REPO_URL}/example-project-app:${{ github.run_number }}
- name: Evidence on docker
run: |
echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > sign.json
jf evd create --package-name example-project-app --package-version ${{ github.run_number }} --package-repo-name ${REPO_NAME} \
--key "${{ secrets.PRIVATE_KEY }}" --key-alias ${{ secrets.KEY_ALIAS }} \
--predicate ./sign.json --predicate-type https://jfrog.com/evidence/signature/v1
echo 'πŸ”Ž Evidence attached: `signature` πŸ” '
- name: Build Attestation Generation
uses: actions/attest-build-provenance@v2
id: attest
with:
subject-name: ${{ steps.docker-build.outputs.image_name }}
subject-digest: ${{ steps.docker-build.outputs.digest }}
push-to-registry: true
- name: Upload Provenance attestation as a Jfrog evidence
id: upload-gh-provenance
run: |
jf evd create --package-name example-project-app --package-version ${{ github.run_number }} --package-repo-name ${REPO_NAME} \
--key "${{ secrets.PRIVATE_KEY }}" --key-alias ${{ secrets.KEY_ALIAS }} \
--predicate ${{ steps.attest.outputs.bundle-path}} --predicate-type https://slsa.dev/provenance/v1
echo 'πŸ”Ž Evidence attached: `provenance` βœ… '
- name: Upload readme file
run: |
jf rt upload ./README.md evidence-demo-generic-dev-local/readme/${{ github.run_number }}/ --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }}
jf evd create --subject-repo-path evidence-demo-generic-dev-local/readme/${{ github.run_number }}/README.md \
--key "${{ secrets.PRIVATE_KEY }}" --key-alias ${{ secrets.KEY_ALIAS }} \
--predicate ./sign.json --predicate-type https://jfrog.com/evidence/signature/v1
- name: Collecting Information from Git
run: jf rt build-add-git ${{ vars.BUILD_NAME }} ${{ github.run_number }}
- name: Collecting Environment Variables
run: jf rt build-collect-env ${{ vars.BUILD_NAME }} ${{ github.run_number }}
- name: Publish build info
run: jfrog rt build-publish ${{ vars.BUILD_NAME }} ${{ github.run_number }}
- name: Sign build evidence
run: |
echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > sign.json
jf evd create --build-name ${{ vars.BUILD_NAME }} --build-number ${{ github.run_number }} \
--predicate ./sign.json --predicate-type https://jfrog.com/evidence/build-signature/v1 \
--key "${{ secrets.PRIVATE_KEY }}" --key-alias ${{ secrets.KEY_ALIAS }}
echo 'πŸ”Ž Evidence attached: `build-signature` πŸ” ' >> $GITHUB_STEP_SUMMARY
- name: Create release bundle
run: |
echo '{ "files": [ {"build": "'"${{ vars.BUILD_NAME }}/${{ github.run_number }}"'" } ] }' > bundle-spec.json
jf release-bundle-create ${{ vars.BUNDLE_NAME }} ${{ github.run_number }} --signing-key ${{ secrets.RB_KEY }} --spec bundle-spec.json --sync=true
NAME_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&repositoryKey=release-bundles-v2&activeKanbanTab=promotion'
VER_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&releaseBundleVersion='${{ github.run_number }}'&repositoryKey=release-bundles-v2&activeVersionTab=Version%20Timeline&activeKanbanTab=promotion'
echo 'πŸ“¦ Release bundle ['${{ vars.BUNDLE_NAME }}']('${NAME_LINK}'):['${{ github.run_number }}']('${VER_LINK}') created' >> $GITHUB_STEP_SUMMARY
Promote-to-qa-and-test:
needs: Docker-build-with-evidence
runs-on: ubuntu-latest
steps:
- name: Install jfrog cli
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- name: Promote to QA
run: |
jf release-bundle-promote ${{ vars.BUNDLE_NAME }} ${{ github.run_number }} QA --signing-key ${{ secrets.RB_KEY }} --sync=true
echo "πŸš€ Succesfully promote to \`QA\` environemnt" >> $GITHUB_STEP_SUMMARY
- name: Evidence on release-bundle
run: |
echo '{ "actor": "${{ github.actor }}", "date": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'" }' > rbv2_evidence.json
JF_LINK=${{ vars.ARTIFACTORY_URL }}'/ui/artifactory/lifecycle/?bundleName='${{ vars.BUNDLE_NAME }}'&bundleToFlash='${{ vars.BUNDLE_NAME }}'&releaseBundleVersion='${{ github.run_number }}'&repositoryKey=release-bundles-v2&activeVersionTab=Version%20Timeline&activeKanbanTab=promotion'
echo 'Test on Release bundle ['${{ vars.BUNDLE_NAME }}':'${{ github.run_number }}']('${JF_LINK}') success' >> $GITHUB_STEP_SUMMARY
jf evd create --release-bundle ${{ vars.BUNDLE_NAME }} --release-bundle-version ${{ github.run_number }} \
--predicate ./rbv2_evidence.json --predicate-type https://jfrog.com/evidence/testing-results/v1 \
--key "${{ secrets.PRIVATE_KEY }}" --key-alias ${{ secrets.KEY_ALIAS }}
echo 'πŸ”Ž Evidence attached: integration-test πŸ§ͺ ' >> $GITHUB_STEP_SUMMARY
Attestation-check-to-promote:
needs: docker-build-with-evidence
runs-on: ubuntu-latest
env:
REPO_NAME: evidence-demo-docker-dev
steps:
- name: Install jfrog cli
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- name: Log in to Artifactory Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ vars.ARTIFACTORY_URL }}
username: ${{ secrets.JF_USER }}
password: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- name: prepare data for validation step
id: prepare-input
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
URL=$(echo ${{ vars.ARTIFACTORY_URL }} | sed 's|^https://||')
echo "repo-url=${URL}/${REPO_NAME}" >> $GITHUB_OUTPUT
- name: Validate the attestation and the artifact
id: verify-attestation
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
IMG_NAME: ${{ needs.docker-build-with-evidence.outputs.image_name }}
run: |
gh attestation verify --owner guybar oci://${{ steps.prepare-input.outputs.repo-url }}/$IMG_NAME --bundle-from-oci --format json
Policy-check-and-promote-to-prod:
needs: Promote-to-qa-and-test
runs-on: ubuntu-latest
steps:
- name: Install jfrog cli
uses: jfrog/setup-jfrog-cli@v4
env:
JF_URL: ${{ vars.ARTIFACTORY_URL }}
JF_ACCESS_TOKEN: ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }}
- name: Checkout
uses: actions/checkout@v4
- name: Install OPA
run: |
curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64
chmod +x opa
sudo mv opa /usr/local/bin/
- name: Call GraphQL
run: |
./scripts/graphql.sh ${{ vars.ARTIFACTORY_URL }} ${{ secrets.ARTIFACTORY_ACCESS_TOKEN }} release-bundles-v2 ${{ vars.BUNDLE_NAME }} ${{ github.run_number }}
cat evidence_graph.json
- name: Run policy
id: run_policy
run: |
result=$(opa eval --input ./evidence_graph.json --data policy/policy.rego "data.greenpizza.output" | jq '.result[0].expressions[0].value.approved')
echo "RESULT=$result" >> $GITHUB_ENV
echo "RESULT=$result" >> $GITHUB_STEP_SUMMARY
- name: Promote to Production
run: |
if [ "${{ env.RESULT }}" == "true" ]; then
opa eval --input ./evidence_graph.json --data policy/policy.rego "data.greenpizza.output" | jq '.result[0].expressions[0].value' > policy.json
cat policy.json
jf evd create --key "${{ secrets.PRIVATE_KEY }}" --key-alias ${{ secrets.KEY_ALIAS }} \
--release-bundle ${{ vars.BUNDLE_NAME }} --release-bundle-version ${{ github.run_number }} \
--predicate ./policy.json --predicate-type https://jfrog.com/evidence/approval/v1
jf release-bundle-promote ${{ vars.BUNDLE_NAME }} ${{ github.run_number }} PROD --signing-key ${{ secrets.RB_KEY }} --sync=true
echo "πŸš€ Succesfully promote to \`PROD\` environemnt" >> $GITHUB_STEP_SUMMARY
else
opa eval --input ./evidence_graph.json --data policy/policy.rego "data.greenpizza.output" | jq '.result[0].expressions[0].value'
echo "Fail promotion policy check" >> $GITHUB_STEP_SUMMARY
exit 1
fi