Skip to content

Build

Build #979

Workflow file for this run

name: Build
on:
push:
branches:
- main
pull_request:
schedule:
- cron: "0 0 * * *"
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
env:
CI: 'true'
jobs:
prepare-env:
name: Prepare environment
runs-on: "ubuntu-latest"
outputs:
requires_tests: ${{ env.REQUIRES_TESTS }}
publish_release: ${{ env.PUBLISH_RELEASE }}
release_version: ${{ env.RELEASE_VERSION }}
release_desc: ${{ env.RELEASE_DESC }}
python_version: ${{ env.PYTHON_VERSION }}
python_major: ${{ env.PYTHON_MAJOR }}
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
if: github.event_name != 'schedule'
- name: Get the changed files that would require tests
id: changed-files
uses: "tj-actions/changed-files@v44"
if: github.event_name != 'schedule'
with:
files: |
apps/**
tests/**
.github/workflows/build.yaml
- name: Check if a new release should be published
if: github.event_name == 'push'
env:
GITHUB_EVENT: ${{ toJSON(github.event) }}
GITHUB_TOKEN: ${{ github.token }}
run: |
.github/workflows/scripts/release.py --printenv | tee -a "$GITHUB_ENV"
- name: Identify if testing is required
run: |
echo "REQUIRES_TESTS=${{ github.event_name == 'schedule' || steps.changed-files.outputs.any_changed == 'true' || steps.changed-files.outputs.any_deleted == 'true' || steps.changed-files.outputs.any_modified == 'true' || env.PUBLISH_RELEASE == 'true' }}" | tee -a "$GITHUB_ENV"
- name: Find python version from AppDaemon's Dockerfile
if: env.REQUIRES_TESTS == 'true'
run: |
# Get the python version from the AppDaemon's Dockerfile
# which was used to build the latest AppDaemon's docker
# container
PYTHON_VERSION=$(\
curl -s https://raw.githubusercontent.com/AppDaemon/appdaemon/dev/Dockerfile | \
grep -oP "(?<=PYTHON_RELEASE=)[0-9\.]*" | head -n1)
echo "PYTHON_VERSION=${PYTHON_VERSION}" | tee -a "$GITHUB_ENV"
PYTHON_MAJOR=${PYTHON_VERSION%%.*}
echo "PYTHON_MAJOR=${PYTHON_MAJOR}" | tee -a "$GITHUB_ENV"
# Exit in error if we were unable to find the python version
if [ -z "$PYTHON_VERSION" ] || [ -z "$PYTHON_MAJOR" ]; then
echo >&2 "Error: unable to find Python version from AppDaemon"
exit 1
fi
unit-integration-tests:
name: Unit & integration tests
runs-on: "ubuntu-latest"
needs:
- prepare-env
if: needs.prepare-env.outputs.requires_tests == 'true'
env:
PYTHON_VERSION: ${{ needs.prepare-env.outputs.python_version }}
PYTHON_MAJOR: ${{ needs.prepare-env.outputs.python_major }}
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
- name: Install python
uses: "actions/setup-python@v5"
with:
python-version: '${{ env.PYTHON_VERSION }}'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest pytest-cov pytest-clarity pytest-subtests
pip install -r tests/requirements.txt
- name: Lint code
id: lint_code
run: |
flake8 apps/
continue-on-error: true
- name: Lint tests
id: lint_tests
run: |
flake8 tests/
continue-on-error: true
- name: Run unit & integration tests
id: tests
run: |
set -eo pipefail
pytest --cache-clear --cov=gateway --cov=qolsys --cov=mqtt --cov-report term-missing --junitxml=pytest.xml tests/unit/ tests/integration/ | tee pytest-coverage.txt
continue-on-error: true
- name: Identify bot comments to hide
uses: actions/github-script@v7
if: steps.tests.outcome == 'success' && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork
with:
script: |
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
})
const botComments = comments.filter(comment => {
return comment.user.type === 'Bot' && comment.body.startsWith('<!-- Pytest Coverage Comment: unit-integration-tests -->')
}).map((comment) => comment.node_id)
if (botComments.length > 0) {
core.exportVariable('BOT_COMMENTS', botComments.join(' '))
console.log('BOT_COMMENTS=' + botComments.join(' '))
}
- name: Minimize comments from previous run
if: steps.tests.outcome == 'success' && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && env.BOT_COMMENTS
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
QUERY=$(cat <<- EOM
mutation minimizeComment(\$id: ID!) {
minimizeComment(input: { classifier: OUTDATED, subjectId: \$id }) {
clientMutationId
}
}
EOM
)
for commentId in ${{ env.BOT_COMMENTS }}; do
gh api graphql -F id="$commentId" -F query="$QUERY"
echo
done
- name: Post comment of pytest coverage
continue-on-error: true
uses: MishaKav/pytest-coverage-comment@main
if: steps.tests.outcome == 'success' && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork
with:
create-new-comment: true
pytest-coverage-path: ./pytest-coverage.txt
junitxml-path: ./pytest.xml
- name: Overall job outcome
run: |
LINT_CODE=$([ '${{ steps.lint_code.outcome }}' == 'success' ] && echo true || echo false)
LINT_TESTS=$([ '${{ steps.lint_tests.outcome }}' == 'success' ] && echo true || echo false)
TESTS=$([ '${{ steps.tests.outcome }}' == 'success' ] && echo true || echo false)
if ! $LINT_CODE; then
echo "Lint of code failed" >&2
fi
if ! $LINT_TESTS; then
echo "Lint of tests failed" >&2
fi
if ! $TESTS; then
echo "Tests failed" >&2
fi
# Exit on error if any failed
if ! $LINT_CODE || ! $LINT_TESTS || ! $TESTS; then
exit 1
fi
exit 0
end-to-end-tests:
name: End-to-end tests
runs-on: "ubuntu-latest"
needs:
- prepare-env
- unit-integration-tests
if: needs.unit-integration-tests.result == 'success'
env:
PYTHON_VERSION: ${{ needs.prepare-env.outputs.python_version }}
PYTHON_MAJOR: ${{ needs.prepare-env.outputs.python_major }}
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
- name: Print docker versions
run: |
docker version
docker compose version
- name: Install python
uses: "actions/setup-python@v5"
with:
python-version: '${{ env.PYTHON_VERSION }}'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest pytest-clarity pytest-subtests
pip install -r tests/requirements.txt
pip install -r tests/end-to-end/requirements.txt
- name: Run end-to-end tests
id: tests
run: |
set -eo pipefail
pytest --cache-clear tests/end-to-end/
update_changelog:
name: Update changelog
runs-on: "ubuntu-latest"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-update-changelog
needs:
- prepare-env
- unit-integration-tests
- end-to-end-tests
if: github.event_name == 'push' && needs.prepare-env.outputs.publish_release != 'true' && needs.unit-integration-tests.result != 'failure' && needs.end-to-end-tests.result != 'failure'
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
with:
ref: ${{ github.ref }}
token: ${{ secrets.COMMIT_TOKEN }}
- name: Update changelog for future release
env:
GITHUB_EVENT: ${{ toJSON(github.event) }}
GITHUB_TOKEN: ${{ github.token }}
run: |
.github/workflows/scripts/release.py --update-changelog
- name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
file_pattern: "info.md"
commit_message: 📒 Update changelog for future release
push_release:
name: Release version
runs-on: ubuntu-latest
needs:
- prepare-env
- unit-integration-tests
- end-to-end-tests
if: github.event_name == 'push' && needs.prepare-env.outputs.publish_release == 'true' && needs.unit-integration-tests.result != 'failure' && needs.end-to-end-tests.result != 'failure'
permissions:
contents: write
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
- name: Release version
uses: ncipollo/release-action@v1
with:
tag: v${{ needs.prepare-env.outputs.release_version }}
name: v${{ needs.prepare-env.outputs.release_version }}
body: ${{ needs.prepare-env.outputs.release_desc }}
commit: main
makeLatest: true
skipIfReleaseExists: true
push_library:
name: Push library to PyPI
runs-on: ubuntu-latest
needs:
- prepare-env
- push_release
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
- name: Install Hatch
uses: pypa/hatch@install
- name: Create version file
env:
VERSION: ${{ needs.prepare-env.outputs.release_version }}
run: |
echo "__version__ = \"${VERSION}\"" | tee build_version.py
- name: Publish to PyPI
run: |
hatch publish
auto-merge:
name: "Auto-merge Dependabot pull requests"
runs-on: ubuntu-latest
needs:
- prepare-env
- unit-integration-tests
- end-to-end-tests
if: github.event_name == 'pull_request' && github.actor == 'dependabot[bot]' && needs.unit-integration-tests.result != 'failure' && needs.end-to-end-tests.result != 'failure'
steps:
- name: Checkout current commit
uses: "actions/checkout@v4"
- name: Check and auto-merge on minor changes
uses: ahmadnassri/action-dependabot-auto-merge@v2
with:
target: minor
github-token: ${{ secrets.AUTOMERGE_TOKEN }}