/deploy sit #178
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Build | |
on: | |
push: | |
branches: [ develop, release/**, main, feature/**, issue/**, dependabot/** ] | |
workflow_dispatch: | |
env: | |
REGISTRY: ghcr.io | |
IMAGE_NAME: ${{ github.repository }} | |
PYTHON_VERSION: '3.11' | |
POETRY_VERSION: '1.8.1' | |
jobs: | |
build: | |
name: Build, Test, Verify, Publish | |
runs-on: ubuntu-latest | |
permissions: | |
contents: write | |
packages: write | |
outputs: | |
version: ${{ steps.versioning.outputs.new_version }} | |
changes: ${{ steps.check_changes.outputs.changes }} | |
pyproject_name: ${{ steps.versioning.outputs.pyproject_name }} | |
steps: | |
- uses: actions/checkout@v4 | |
with: | |
fetch-depth: 0 # Needed for proper versioning | |
- name: Setup Python and Poetry | |
uses: ./.github/workflows/setup-python-poetry | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
poetry-version: ${{ env.POETRY_VERSION }} | |
- name: Version Management | |
id: versioning | |
run: | | |
# Combine version management logic into a single step | |
pyproject_name=$(poetry version | awk '{print $1}') | |
echo "pyproject_name=${pyproject_name}" >> $GITHUB_OUTPUT | |
current_version=$(poetry version -s) | |
echo "old_version=${current_version}" >> $GITHUB_ENV | |
# Version calculation based on branch | |
if [[ "${{ github.ref }}" =~ ^refs/heads/(issue|feature|dependabot)/ ]]; then | |
new_version="${current_version%%-*}+$(git rev-parse --short HEAD)" | |
elif [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then | |
if [[ ${current_version} =~ -alpha ]]; then | |
alpha_num=$((${current_version##*alpha.} + 1)) | |
new_version="${current_version%%-*}-alpha.${alpha_num}" | |
else | |
new_version="${current_version}-alpha.1" | |
fi | |
elif [[ "${{ github.ref }}" =~ ^refs/heads/release/ ]]; then | |
if [[ ${current_version} =~ -rc ]]; then | |
rc_num=$((${current_version##*rc.} + 1)) | |
new_version="${current_version%%-*}-rc.${rc_num}" | |
else | |
new_version="${current_version}-rc.1" | |
fi | |
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
new_version=${current_version%%-*} | |
fi | |
echo "new_version=${new_version}" >> $GITHUB_OUTPUT | |
poetry version ${new_version} | |
- name: Install Dependencies and Run Tests | |
run: | | |
poetry install | |
poetry run pylint podaac | |
poetry run flake8 podaac | |
poetry run pytest --junitxml=build/reports/pytest.xml --cov=podaac/ --cov-report=html -m "not aws and not integration" tests/ | |
- name: Security Scan | |
uses: snyk/actions/python@master | |
env: | |
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} | |
with: | |
command: test | |
args: --org=${{ secrets.SNYK_ORG_ID }} --project-name=${{ github.repository }} --severity-threshold=high --fail-on=all | |
- name: Build Package | |
run: poetry build | |
- name: Quick check for changes | |
id: check_changes | |
if: | | |
github.ref == 'refs/heads/develop' || | |
github.ref == 'refs/heads/main' || | |
startsWith(github.ref, 'refs/heads/release') | |
run: | | |
if [ -n "$(git status --porcelain)" ]; then | |
echo "changes=true" >> $GITHUB_OUTPUT | |
else | |
echo "changes=false" >> $GITHUB_OUTPUT | |
fi | |
- name: Commit Version Bump | |
if: steps.check_changes.outputs.changes == 'true' | |
run: | | |
git config user.name "${GITHUB_ACTOR}" | |
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" | |
git commit -am "/version ${{ env.the_version }}" | |
git push | |
- name: Push Tag | |
env: | |
VERSION: ${{ env.the_version }} | |
if: | | |
github.ref == 'refs/heads/develop' || | |
github.ref == 'refs/heads/main' || | |
startsWith(github.ref, 'refs/heads/release') | |
run: | | |
git config user.name "${GITHUB_ACTOR}" | |
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" | |
git tag -a "${VERSION}" -m "Version ${VERSION}" | |
git push origin "${VERSION}" | |
- name: Create and Upload Release | |
if: | | |
github.ref == 'refs/heads/develop' || | |
github.ref == 'refs/heads/main' || | |
startsWith(github.ref, 'refs/heads/release') | |
uses: ncipollo/release-action@v1.14.0 | |
with: | |
tag: ${{ env.new_version }} | |
artifacts: "*.zip" | |
token: ${{ secrets.GITHUB_TOKEN }} | |
makeLatest: ${{ github.ref == 'refs/heads/main' }} | |
prerelease: ${{ github.ref != 'refs/heads/main' }} | |
publish: | |
name: Build & Publish Docker | |
needs: build | |
if: | | |
success() && ( | |
github.ref == 'refs/heads/develop' || | |
github.ref == 'refs/heads/main' || | |
startsWith(github.ref, 'refs/heads/release') || | |
contains(github.event.head_commit.message, '/deploy') | |
) | |
runs-on: ubuntu-latest | |
permissions: | |
packages: write | |
steps: | |
- uses: actions/checkout@v4 | |
- name: Setup Python and Poetry | |
uses: ./.github/workflows/setup-python-poetry | |
with: | |
python-version: ${{ env.PYTHON_VERSION }} | |
poetry-version: ${{ env.POETRY_VERSION }} | |
- name: Set up QEMU | |
uses: docker/setup-qemu-action@v3 | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@v3 | |
- name: Build Package | |
run: poetry build | |
- name: Get Local Forge-py Build | |
if: contains(github.event.head_commit.message, '/deploy') | |
run: | | |
local_forge_py=$(find dist -type f -name "*.whl") | |
echo "local_forge_py=${local_forge_py}" >> $GITHUB_ENV | |
- name: Publish to PyPI | |
if: "!contains(github.event.head_commit.message, '/deploy')" | |
env: | |
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_API_TOKEN }} | |
POETRY_PYPI_TOKEN_TESTPYPI: ${{ secrets.TEST_PYPI_API_TOKEN }} | |
run: | | |
if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
poetry publish | |
else | |
poetry config repositories.testpypi https://test.pypi.org/legacy/ | |
poetry publish -r testpypi | |
fi | |
- name: Wait for package | |
if: | | |
github.ref == 'refs/heads/develop' || | |
github.ref == 'refs/heads/main' || | |
startsWith(github.ref, 'refs/heads/release/') | |
run: | | |
pip install tenacity logging | |
python3 ${GITHUB_WORKSPACE}/.github/workflows/wait-for-pypi.py ${{needs.build.outputs.pyproject_name}}[harmony]==${{ needs.build.outputs.version }} | |
- name: Set Environment Variables | |
run: | | |
if [[ "${{ github.ref }}" == "refs/heads/develop" ]]; then | |
echo "TARGET_ENV_UPPERCASE=SIT" >> $GITHUB_ENV | |
elif [[ "${{ github.ref }}" =~ ^refs/heads/release/ ]]; then | |
echo "TARGET_ENV_UPPERCASE=UAT" >> $GITHUB_ENV | |
elif [[ "${{ github.ref }}" == "refs/heads/main" ]]; then | |
echo "TARGET_ENV_UPPERCASE=OPS" >> $GITHUB_ENV | |
fi | |
- name: Deploy Env Override | |
if: contains(github.event.head_commit.message, '/deploy') | |
run: | | |
message="${{ github.event.head_commit.message }}" | |
trimmed_message=${message:1} # Remove leading slash | |
override_env=$(echo "$trimmed_message" | grep -oE '[^[:space:]]+$') | |
override_env_upper=$(echo "$trimmed_message" | awk '{print toupper($NF)}') | |
echo "TARGET_ENV_UPPERCASE=${override_env_upper}" >> $GITHUB_ENV | |
- name: Lower Case Target Env | |
run: | | |
original_env_value="${TARGET_ENV_UPPERCASE}" | |
lowercase_value=$(echo "${original_env_value}" | tr '[:upper:]' '[:lower:]') | |
echo "TARGET_ENV_LOWERCASE=${lowercase_value}" >> $GITHUB_ENV | |
- name: Extract metadata (tags, labels) for Docker | |
if: | | |
steps.pypi-test-publish.conclusion == 'success' || | |
steps.pypi-publish.conclusion == 'success' || | |
github.event.head_commit.message == '/deploy sit' || | |
github.event.head_commit.message == '/deploy uat' || | |
github.event.head_commit.message == '/deploy sandbox' | |
id: meta | |
uses: docker/metadata-action@v5 | |
with: | |
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
flavor: | | |
latest=${{ github.ref == 'refs/heads/main' }} | |
tags: | | |
type=semver,pattern={{raw}},value=${{ needs.build.outputs.version }} | |
type=raw,value=${{ env.TARGET_ENV_LOWERCASE }} | |
- name: Set Build Source | |
id: set-source | |
run: | | |
# Default build source for standard branches | |
echo "SOURCE=${{ env.pyproject_name }}==${{ env.the_version }}" >> $GITHUB_ENV | |
# Override source if deploying (find .whl file in dist/) | |
if [[ "${{ contains(github.event.head_commit.message, '/deploy sit') || | |
contains(github.event.head_commit.message, '/deploy uat') || | |
contains(github.event.head_commit.message, '/deploy sandbox') }}" == "true" ]]; then | |
local_forge_py=$(find dist -type f -name "*.whl") | |
echo "SOURCE=${local_forge_py}" >> $GITHUB_ENV | |
echo "DIST_PATH=dist/" >> $GITHUB_ENV | |
fi | |
- name: Build and Push Docker Image | |
uses: docker/build-push-action@v3 | |
with: | |
context: . | |
file: ./docker/lambdaDockerfileArm | |
push: true | |
pull: true | |
tags: ${{ steps.meta.outputs.tags }} | |
labels: ${{ steps.meta.outputs.labels }} | |
platforms: linux/arm/v7 | |
build-args: | | |
SOURCE=${{ env.SOURCE }} | |
DIST_PATH=${{ env.DIST_PATH || '' }} |