Skip to content

feat: obtain Java and Python artifacts from .m2 or Python virtual env… #371

feat: obtain Java and Python artifacts from .m2 or Python virtual env…

feat: obtain Java and Python artifacts from .m2 or Python virtual env… #371

Workflow file for this run

# Copyright (c) 2022 - 2023, Oracle and/or its affiliates. All rights reserved.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/.
# We run checks on pushing to the specified branches.
# Pushing to main also triggers a release.
name: Check and Release
on:
push:
branches:
- main
- staging
permissions:
contents: read
env:
ARTIFACT_NAME: artifact-ubuntu-latest-python-3.11
# This is the username and email for the user who commits and pushes the release
# commit. In an organisation that should be a dedicated devops account.
USER_NAME: behnazh-w
USER_EMAIL: [email protected]
IMAGE_NAME: ghcr.io/oracle/macaron
jobs:
check:
if: ${{ !startsWith(github.event.commits[0].message, 'bump:') }}
uses: ./.github/workflows/_build.yaml
permissions:
contents: read
packages: read
# On pushes to the 'main' branch create a new release by bumping the version
# and generating a change log. That's the new bump commit and associated tag.
bump:
needs: check
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Check out repository
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
with:
fetch-depth: 0
token: ${{ secrets.REPO_ACCESS_TOKEN }}
- name: Set up Python
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
with:
python-version: '3.11'
# Prepare the environment to run commitizen.
- name: Create empty virtual environment for Actions
run: mkdir .venv
- name: Install dependencies
run: make setup-github-actions
- name: Set up user
run: |
git config --global user.name "$USER_NAME"
git config --global user.email "$USER_EMAIL"
git config --list --global # For debug purposes.
# In some cases a user may merge commits that don't cause a version bump, which causes commitizen
# to fail with error code 21 (NoneIncrementExit). Thus we silence that particular error to avoid
# failing this job: https://commitizen-tools.github.io/commitizen/bump/#avoid-raising-errors
- name: Create changelog and bump
run: cz --no-raise 21 bump --changelog --yes
- name: Push the release
run: |
git push
git push --tags
# After the bump commit was pushed to the main branch, rebase the staging branch
# (to_head argument) on top of the new main branch (from_base argument), to keep
# the histories of both branches in sync.
rebase_staging:
needs: [bump]
name: Rebase staging branch on main
uses: ./.github/workflows/_generate-rebase.yaml
permissions:
contents: read
with:
to_head: staging
from_base: origin/main
git_user_name: behnazh-w
git_user_email: [email protected]
secrets:
REPO_ACCESS_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
# When triggered by the version bump commit, build the package and publish the release artifacts.
build:
if: github.ref == 'refs/heads/main' && startsWith(github.event.commits[0].message, 'bump:')
uses: ./.github/workflows/_build.yaml
permissions:
contents: read
packages: read
# Create a new Release on GitHub from the verified build artifacts, and optionally
# publish the artifacts to a PyPI server.
release:
needs: [build]
name: Release
outputs:
release-tag: ${{ steps.release-info.outputs.release-tag }}
release-version: ${{ steps.release-info.outputs.release-version }}
release-url: ${{ steps.release-info.outputs.release-url }}
image-name: ${{ steps.push-docker.outputs.image-name }}
image-digest: ${{ steps.push-docker.outputs.image-digest }}
runs-on: ubuntu-latest
permissions:
contents: write # To publish release notes.
packages: write # To push the Docker image.
steps:
- name: Check out repository
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
with:
fetch-depth: 0
# Determine the release tag and url, and set them as outputs.
- name: Determine release info
id: release-info
run: |
TAG=$(git describe --tags --abbrev=0)
{
echo "release-tag=$TAG"
echo "release-version=${TAG#v}"
echo "release-url=$(gh release view """$TAG""" --json url --jq .url)"
} >> "$GITHUB_OUTPUT"
- name: Download artifact
uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
with:
name: ${{ env.ARTIFACT_NAME }}
path: dist
# Verify hashes by first computing hashes for the artifacts and then comparing them
# against the hashes computed by the build job.
- name: Verify the artifact hash
env:
ARTIFACT_HASH: ${{ needs.build.outputs.artifacts-sha256 }}
run: |
set -euo pipefail
echo "Hash of package should be $ARTIFACT_HASH."
echo "$ARTIFACT_HASH" | base64 --decode | sha256sum --strict --check --status || exit 1
# Log in to ghcr.io to push the Docker image.
- name: Log in to GitHub Container Registry
run: docker login ghcr.io --username ${{ github.actor }} --password ${{ secrets.GITHUB_TOKEN }}
# Build the Docker image with tags: latest and RELEASE_TAG
- name: Build the Docker image
env:
RELEASE_TAG: ${{ steps.release-info.outputs.release-tag }}
run: make build-docker
# Push the Docker image as part of the release pipeline.
- name: Push the Docker image
id: push-docker
env:
RELEASE_TAG: ${{ steps.release-info.outputs.release-tag }}
run: |
make push-docker
IMAGE_AND_DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "$IMAGE_NAME")
NAME=$(echo "$IMAGE_AND_DIGEST" | cut -d'@' -f1 | cut -d':' -f1)
DIGEST=$(echo "$IMAGE_AND_DIGEST" | cut -d'@' -f2)
{
echo "image-name=${NAME}"
echo "image-digest=${DIGEST}"
} >> "$GITHUB_OUTPUT"
# Generate the Docker image SBOM under the dist/ directory which will be published as part of the release assets.
- name: Generate Docker sbom
env:
SYFT_BIN: ${{ github.workspace }}/bin
RELEASE_TAG: ${{ steps.release-info.outputs.release-tag }}
RELEASE_VERSION: ${{ steps.release-info.outputs.release-version }}
SYFT_VERSION: 0.84.0
# We install Syft, which is an SBOM generator tool for Docker images, using the instructions from:
# https://github.com/anchore/syft#installation
# We only generate SBOM in CycloneDX format.
run: |
mkdir -p "$SYFT_BIN"
ASSET_NAME="syft_${SYFT_VERSION}_linux_amd64.tar.gz"
CHECKSUMS="syft_${SYFT_VERSION}_checksums.txt"
# Download artifacts.
echo "Downloading $ASSET_NAME"
curl --output "$ASSET_NAME" --progress-bar --location \
"https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/${ASSET_NAME}"
test -s "$ASSET_NAME" || (echo "Unable to download $ASSET_NAME" && exit 0)
echo "Downloading $CHECKSUMS"
curl --output "$CHECKSUMS" --progress-bar --location \
"https://github.com/anchore/syft/releases/download/v${SYFT_VERSION}/${CHECKSUMS}"
test -s "$CHECKSUMS" || (echo "Unable to download $CHECKSUMS" && exit 0)
EXPECTED=$(grep "${ASSET_NAME}" "${CHECKSUMS}" 2>/dev/null | tr '\t' ' ' | cut -d ' ' -f 1)
SYFT_DIGEST=$(sha256sum "$ASSET_NAME" | cut -d ' ' -f 1)
# Check if artifact is valid.
if [ "$EXPECTED" == "$SYFT_DIGEST" ]; then
tar -zxvf "$ASSET_NAME" -C "$SYFT_BIN" syft
"$SYFT_BIN"/syft --version
"$SYFT_BIN"/syft \
ghcr.io/oracle/macaron:"$RELEASE_TAG" \
-o cyclonedx-json=dist/macaron-"$RELEASE_VERSION"-sbom-docker.json
else
echo "Checksum for '$ASSET_NAME' did not verify: expected $EXPECTED but got $SYFT_DIGEST"
fi
# Remove the downloaded artifacts.
rm -f "$ASSET_NAME"
rm -f "$CHECKSUMS"
- name: Set up Python
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
with:
python-version: '3.11'
# Prepare the environment to run commitizen.
- name: Create empty virtual environment for Actions
run: mkdir .venv
- name: Install dependencies
run: make setup-github-actions
# Create the Release Notes using commitizen.
- name: Create Release Notes
run: cz changelog --dry-run "$(cz version --project)" > RELEASE_NOTES.md
# Create the release including the artifacts and the SLSA L3 provenance.
- name: Upload assets
id: upload-assets
env:
GH_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
RELEASE_TAG: ${{ steps.release-info.outputs.release-tag }}
run: gh release create "$RELEASE_TAG" dist/* --title "$RELEASE_TAG" --notes-file RELEASE_NOTES.md
# Uncomment the following steps to publish to a PyPI server.
# At the moment PyPI does not provide a mechanism to publish
# the provenance. So, users have to download the provenance from
# the release page of the GitHub repository to verify the artifact.
# Install Twine without using the package's Makefile to avoid
# installing unnecessary dependencies, which is slow.
# - name: Set up Twine
# run: |
# pip install --upgrade pip wheel
# pip install 'twine ==4.0.1'
# Pass the username, password, and PYPI repository URL via env variables.
# Read the password from GitHub secrets or via other trusted mechanisms.
# Do not hardcode the password in the workflow.
# - name: Publish to PyPI server
# run: twine upload --verbose dist/*.tar.gz dist/*.whl
# env:
# TWINE_USERNAME=<USERNAME>
# TWINE_PASSWORD=<PASSWORD>
# TWINE_REPOSITORY_URL=<REPOSITORY_URL>
# Uncomment the provenance generation once we have approval for running its third-party
# GitHub Actions. See https://github.com/slsa-framework/slsa-github-generator/issues/2204.
# Generate the build provenance. The generator should be referenced with a semantic version.
# The build will fail if we reference it using the commit SHA. To avoid using a pre-built
# provenance generator which depends on an external service Rekor (https://github.com/sigstore/rekor)
# we build this generator from source for now. For more information see this discussion:
# https://github.com/slsa-framework/slsa-github-generator/issues/942
# provenance:
# needs: [build, release]
# uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
# with:
# base64-subjects: ${{ needs.build.outputs.artifacts-sha256 }}
# compile-generator: true # Build the generator from source.
# # Set private-repository to true for private repositories. Note that the repository name is
# # uploaded as part of the transparency log entry on the public Rekor instance (rekor.sigstore.dev).
# private-repository: false
# provenance-name: macaron-${{ needs.release.outputs.release-version }}.intoto.jsonl
# permissions:
# actions: read # To read the workflow path.
# id-token: write # To sign the provenance.
# contents: write # To add assets to a release.
# Generate SLSA provenance for the Docker image and push it to the container registry.
# provenance-docker:
# needs: [release]
# permissions:
# actions: read # To detect the GitHub Actions environment.
# id-token: write # To create OIDC tokens for signing.
# packages: write # To upload provenance.
# uses: slsa-framework/slsa-github-generator/.github/workflows/[email protected]
# with:
# image: ${{ needs.release.outputs.image-name }}
# digest: ${{ needs.release.outputs.image-digest }}
# registry-username: ${{ github.actor }}
# secrets:
# registry-password: ${{ secrets.GITHUB_TOKEN }}
# Publish the SLSA provenance as the GitHub release asset.
# publish_provenance:
# needs: [release, provenance]
# name: Publish provenance
# runs-on: ubuntu-latest
# permissions:
# contents: write # To publish release notes.
# steps:
# - name: Check out repository
# uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
# with:
# fetch-depth: 0
# - name: Download provenance
# uses: actions/download-artifact@65a9edc5881444af0b9093a5e628f2fe47ea3b2e # v4.1.7
# with:
# name: ${{ needs.provenance.outputs.provenance-name }}
# - name: Upload provenance
# run: gh release upload ${{ needs.release.outputs.release-tag }} ${{ needs.provenance.outputs.provenance-name }}
# env:
# GH_TOKEN: ${{ secrets.REPO_ACCESS_TOKEN }}
# Publish docs to GitHub pages.
github-pages:
needs: [build, release]
name: Deploy GitHub pages
uses: ./.github/workflows/_deploy-github-pages.yaml
permissions:
contents: read
pages: write
id-token: write
with:
# TODO: use ${{ env.ARTIFACT_NAME }} when this issue is addressed:
# https://github.com/actions/runner/issues/2394.
artifact-name: artifact-ubuntu-latest-python-3.11
artifact-sha256: ${{ needs.build.outputs.artifacts-sha256 }}
# Send out release notifications after the Release was published on GitHub.
# Uncomment the `if` to disable sending release notifications.
notifications:
if: ${{ false }}
needs: [release]
name: Send Release notifications
uses: ./.github/workflows/_release-notifications.yaml
permissions:
contents: read
with:
repo_name: ${{ github.event.repository.name }}
release_tag: ${{ needs.release.outputs.release-tag }}
release_url: ${{ needs.release.outputs.release-url }}
secrets:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}