Skip to content

Commit

Permalink
Enable GitHub Actions
Browse files Browse the repository at this point in the history
Signed-off-by: Keith Battocchi <kebatt@microsoft.com>
  • Loading branch information
kbattocchi committed Mar 17, 2023
1 parent d1baba1 commit 4c9f413
Show file tree
Hide file tree
Showing 6 changed files with 429 additions and 400 deletions.
230 changes: 230 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
name: Run all checks for pull requests

on:
pull_request:
branches:
- main
workflow_dispatch:
inputs:
ref:
description: 'The git ref to build the package for'
required: false
default: ''
type: string

# Precompute the ref if the workflow was triggered by a workflow dispatch rather than copying this logic repeatedly
env:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || null }}

jobs:
eval:
name: Evaluate changes
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout repository
with:
ref: ${{ env.ref }}
fetch-depth: 2

# We want to enforce the following rules for PRs:
# * if all modifications are to README.md
# no testing is needed
# * if there are modifications to docs/* or to any code
# then docs need to be built to verify consistency
# * if there are modifications to notebooks/* or to any code
# then notebooks need to be run to verify consistency
# * for any code changes (or changes to metadata files)
# linting and testing should be run
# For a PR build, HEAD will be the merge commit, and we want to diff against the base branch,
# which will be the first parent: HEAD^
# (For non-PR changes, we will always perform all CI tasks)
# Note that GitHub Actions provides path filters, but they operate at the workflow level, not the job level
- run: |
if ($env:GITHUB_EVENT_NAME -eq 'pull_request') {
$editedFiles = git diff HEAD^ --name-only
$editedFiles # echo edited files to enable easier debugging
$codeChanges = $false
$docChanges = $false
$nbChanges = $false
$changeType = "none"
foreach ($file in $editedFiles) {
switch -Wildcard ($file) {
"README.md" { Continue }
".gitignore" { Continue }
"econml/_version.py" { Continue }
"prototypes/*" { Continue }
"images/*" { Continue }
"doc/*" { $docChanges = $true; Continue }
"notebooks/*" { $nbChanges = $true; Continue }
default { $codeChanges = $true; Continue }
}
}
}
echo "buildDocs=$(($env:GITHUB_EVENT_NAME -ne 'pull_request') -or ($docChanges -or $codeChanges))" >> $env:GITHUB_OUTPUT
echo "buildNbs=$(($env:GITHUB_EVENT_NAME -ne 'pull_request') -or ($nbChanges -or $codeChanges))" >> $env:GITHUB_OUTPUT
echo "testCode=$(($env:GITHUB_EVENT_NAME -ne 'pull_request') -or $codeChanges)" >> $env:GITHUB_OUTPUT
shell: pwsh
name: Determine type of code change
id: eval
outputs:
buildDocs: ${{ steps.eval.outputs.buildDocs }}
buildNbs: ${{ steps.eval.outputs.buildNbs }}
testCode: ${{ steps.eval.outputs.testCode }}

lint:
name: Lint code
needs: [eval]
if: ${{ needs.eval.outputs.testCode == 'True' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout repository
with:
ref: ${{ env.ref }}
- uses: actions/setup-python@v4
name: Setup Python
with:
python-version: 3.9
- run: python -m pip install --upgrade pip && pip install --upgrade setuptools
name: Ensure latest pip and setuptools
- run: 'pip install pycodestyle && pycodestyle econml'

notebooks:
name: Run notebooks
needs: [eval]
if: ${{ needs.eval.outputs.buildNbs == 'True' }}
runs-on: ubuntu-latest
strategy:
matrix:
kind: [except customer scenarios, customer scenarios]
include:
- kind: "except customer scenarios"
extras: "[tf,plt]"
pattern: "(?!CustomerScenarios)"
install_graphviz: true
version: 3.8 # no supported version of tensorflow for 3.9
- kind: "customer scenarios"
extras: "[plt,dowhy]"
pattern: "CustomerScenarios"
version: 3.9
install_graphviz: false
fail-fast: false
steps:
- uses: actions/checkout@v3
name: Checkout repository
with:
ref: ${{ env.ref }}
- uses: actions/setup-python@v4
name: Setup Python
with:
python-version: ${{ matrix.version }}
- run: python -m pip install --upgrade pip && pip install --upgrade setuptools
name: Ensure latest pip and setuptools
- run: sudo apt-get -yq install graphviz
name: Install graphviz
if: ${{ matrix.install_graphviz }}
- run: pip install -e .${{ matrix.extras }}
name: Install econml
- run: pip install pytest pytest-runner jupyter jupyter-client nbconvert nbformat seaborn xgboost tqdm
name: Install test and notebook requirements
- run: pip list
name: List installed packages
- run: python setup.py pytest
name: Run notebook tests
env:
PYTEST_ADDOPTS: '-m "notebook"'
NOTEBOOK_DIR_PATTERN: ${{ matrix.pattern }}

tests:
name: "Run tests"
needs: [eval]
if: ${{ needs.eval.outputs.testCode == 'True' }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: [3.6, 3.7, 3.8, 3.9]
kind: [serial, other, dml, main, treatment]
exclude:
# Serial tests fail randomly on mac sometimes, so we don't run them there
- os: macos-latest
kind: serial
# Python 3.6 isn't supported on ubuntu-latest
- os: ubuntu-latest
python-version: 3.6

# Assign the correct package and testing options for each kind of test
include:
- kind: serial
opts: '-m "serial" -n 1'
extras: "[tf,plt]"
- kind: other
opts: '-m "cate_api" -n auto'
extras: "[tf,plt]"
- kind: dml
opts: '-m "dml"'
extras: "[tf,plt]"
- kind: main
opts: '-m "not (notebook or automl or dml or serial or cate_api or treatment_featurization)" -n 2'
extras: "[tf,plt,dowhy]"
- kind: treatment
opts: '-m "treatment_featurization" -n auto'
extras: "[tf,plt]"
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
name: Checkout repository
with:
ref: ${{ env.ref }}
- uses: actions/setup-python@v4
name: Setup Python
with:
python-version: ${{ matrix.python-version }}
- run: python -m pip install --upgrade pip && pip install --upgrade setuptools
name: Ensure latest pip and setuptools
- run: pip install -e .${{ matrix.extras }}
name: Install econml
- run: pip install pytest pytest-runner coverage
name: Install pytest
- run: python setup.py pytest
name: Run tests
env:
PYTEST_ADDOPTS: ${{ matrix.opts }}
COVERAGE_PROCESS_START: 'setup.cfg'
# todo: publish test results, coverage info

build:
name: Build package
needs: [eval]
if: ${{ needs.eval.outputs.testCode == 'True' }}
uses: ./.github/workflows/publish-package.yml
with:
publish: false
repository: testpypi
# don't have access to env context here for some reason
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || null }}

docs:
name: Build documentation
needs: [eval]
if: ${{ needs.eval.outputs.buildDocs == 'True' }}
uses: ./.github/workflows/publish-documentation.yml
with:
publish: false
environment: test
# don't have access to env context here for some reason
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.ref || null }}

verify:
name: Verify CI checks
needs: [lint, notebooks, tests, build, docs]
if: always()
runs-on: ubuntu-latest
steps:
- run: exit 1
name: At least one check failed or was cancelled
if: ${{ !(success()) }}
- run: exit 0
name: All checks passed
if: ${{ success() }}
80 changes: 80 additions & 0 deletions .github/workflows/publish-documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: Build and publish the documentation
on:
workflow_dispatch:
inputs:
publish:
description: 'Whether to publish the documentation (as opposed to just building it)'
required: false
default: true
type: boolean
environment:
description: 'Whether to publish to production or test environment'
required: false
default: prod
type: choice
options: [prod, test]
ref:
description: 'The git ref to build the documentation for'
required: false
default: ''
type: string
# annoyingly, there does not seem to be a way to share these input definitions between triggers
workflow_call:
inputs:
publish:
description: 'Whether to publish the documentation (as opposed to just building it)'
required: false
default: true
type: boolean
# choice type only supported for workflow_dispatch, not workflow_call
environment:
description: 'Whether to publish to production or test environment'
required: false
default: prod
type: string
ref:
description: 'The git ref to build the documentation for'
required: false
default: ''
type: string


jobs:
create_docs:
name: Create and publish documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
name: Checkout repository
with:
ref: ${{ inputs.ref }}
- uses: actions/setup-python@v4
name: Setup Python
with:
python-version: 3.8 # because of our supported TensorFlow versions, must build on 3.6-3.8
- run: python -m pip install --upgrade pip && pip install --upgrade setuptools
name: Ensure latest pip and setuptools
- run: pip install -U cython && pip install -e .[all]
name: Install econml[all]
- run: sudo apt-get -yq install graphviz
name: Install graphviz
- run: pip install "sphinx~=4.4.0" "sphinx_rtd_theme~=1.0.0" && python setup.py build_sphinx -W
name: Build documentation
- uses: actions/upload-artifact@v3
name: Upload docs as artifact
with:
name: docs
path: build/sphinx/html/
- run: |-
pushd build/sphinx/html
zip -r docs.zip *
popd
name: Zip docs for publishing
if : ${{ inputs.publish }}
- uses: azure/webapps-deploy@v2
name: Deploy documentation to Azure web app
with:
app-name: ${{ inputs.environment == 'prod' && 'econml' || 'econml-dev' }}
package: build/sphinx/html/docs.zip
publish-profile: ${{ inputs.environment == 'prod' && secrets.PROD_WEBAPP_PUBLISH_PROFILE || secrets.STAGING_WEBAPP_PUBLISH_PROFILE }}
if: ${{ inputs.publish }}
Loading

0 comments on commit 4c9f413

Please sign in to comment.