/deploy sit #167
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: Check for Changes | |
id: check_changes | |
if: | | |
github.ref == 'refs/heads/develop' || | |
github.ref == 'refs/heads/main' || | |
startsWith(github.ref, 'refs/heads/release') | |
run: | | |
git diff --quiet || echo "changes=true" >> $GITHUB_OUTPUT | |
- name: Git Operations | |
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.new_version }}" | |
git tag -a "${{ env.new_version }}" -m "Version ${{ env.new_version }}" | |
git push --follow-tags | |
- 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: | |
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: 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: Build and Push Docker Image | |
uses: docker/build-push-action@v6 | |
with: | |
context: . | |
file: ./docker/lambdaDockerfileArm | |
push: true | |
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.version }} | |
labels: ${{ steps.meta.outputs.labels }} | |
platforms: linux/arm64 | |
build-args: | | |
DIST_PATH: ${{ contains(github.event.head_commit.message, '/deploy') && 'dist/' || '' }} | |
SOURCE: ${{ env.local_forge_py != '' && env.local_forge_py || format('{0}=={1}', needs.build.outputs.pyproject_name, needs.build.outputs.version) }} |