diff --git a/.Rbuildignore b/.Rbuildignore
index d811a530db2d2beca306e37e15ab5f8bb995ab66..4046e017d00f8a92b584f4990200cc9e46a3a468 100644
--- a/.Rbuildignore
+++ b/.Rbuildignore
@@ -1,9 +1,9 @@
 ^.*\.Rproj$
 ^\.Rproj\.user$
-.travis.yml
 demo.R
 _pkgdown.yml
 docs
 DISCLAIMER.md
 code.json
-appveyor.yml
\ No newline at end of file
+appveyor.yml
+.github
\ No newline at end of file
diff --git a/.github/workflows/R-CMD-check.yml b/.github/workflows/R-CMD-check.yml
new file mode 100644
index 0000000000000000000000000000000000000000..46b15a938522b75d64502c98cb25cbef34d5b02e
--- /dev/null
+++ b/.github/workflows/R-CMD-check.yml
@@ -0,0 +1,78 @@
+on:
+  push:
+    branches:
+      - master
+  pull_request:
+    branches:
+      - master
+
+name: R-CMD-check
+
+jobs:
+  R-CMD-check:
+    runs-on: ubuntu-18.04
+    env:
+      R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
+      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
+      _R_CHECK_TESTS_NLINES_: 0
+    steps:
+      - uses: actions/checkout@v2
+
+      - uses: r-lib/actions/setup-r@v1
+
+      - name: Query dependencies
+        run: |
+          install.packages('remotes')
+          saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2)
+          writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version")
+        shell: Rscript {0}
+
+      - name: Cache R packages
+        if: runner.os != 'Windows'
+        uses: actions/cache@v2
+        with:
+          path: ${{ env.R_LIBS_USER }}
+          key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }}
+          restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-
+
+      - name: Install system dependencies
+        if: runner.os == 'Linux'
+        env:
+          RHUB_PLATFORM: linux-x86_64-ubuntu-gcc
+        run: |
+          Rscript -e "remotes::install_github('r-hub/sysreqs')"
+          sysreqs=$(Rscript -e "cat(sysreqs::sysreq_commands('DESCRIPTION'))")
+          sudo -s eval "$sysreqs"
+
+          # install spatial dependencies
+          sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable
+          sudo apt update
+          sudo apt install \
+            libudunits2-dev \
+            libgdal-dev \
+            libgeos-dev \
+            libproj-dev
+
+
+      - name: Install dependencies
+        run: |
+          install.packages(c("remotes"))
+          remotes::install_deps(dependencies = TRUE)
+          remotes::install_cran("rcmdcheck")
+          remotes::install_cran("covr")
+        shell: Rscript {0}
+
+      - name: Check
+        run: rcmdcheck::rcmdcheck(args = c("--ignore-vignettes", "--no-manual"), build_args = c("--no-build-vignettes"), error_on = "error", check_dir = "check")
+        shell: Rscript {0}
+
+      - name: Upload check results
+        if: failure()
+        uses: actions/upload-artifact@master
+        with:
+          name: results
+          path: check
+
+      - name: Test coverage
+        run: covr::codecov()
+        shell: Rscript {0}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 8be95cf00afc496728206a6f8b60659d802ad18f..0000000000000000000000000000000000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-language: r
-
-cache:
-  - packages
-  - ccache
-
-sudo: required
-dist: xenial
-latex: false
-
-r:
-  - release
-
-addons:
-  apt:
-    sources:
-      - sourceline: 'ppa:ubuntugis/ubuntugis-unstable'
-    packages:
-      - libudunits2-dev
-      - libproj-dev
-      - libgeos-dev
-      - libgdal-dev
-      - netcdf-bin
-
-env:
-   global:
-     - NOT_CRAN="true"
-     - _R_CHECK_FORCE_SUGGESTS_=false
-     - R_CODECOV=true
-
-warnings_are_errors: false
-
-r_check_args: "--no-build-vignettes --no-manual --as-cran"
-r_build_args: "--no-build-vignettes --no-manual"
-
-r_github_packages:
-  - jimhester/covr
-  
-after_success:
-  - if [[ "${R_CODECOV}" ]]; then R -e 'covr::coveralls()'; fi
-
-notifications:
-  email:
-    on_success: change
-    on_failure: change
diff --git a/README.md b/README.md
index 5aec6e1eeea5043c0e3c892ee3a69f5763c646dd..faaf9f0e84d7397e055b66cd82543a115a224dd7 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 NetCDF-CF Geometry and Timeseries Tools for R
 ===
-[![Build Status](https://travis-ci.org/USGS-R/ncdfgeom.svg)](https://travis-ci.org/USGS-R/ncdfgeom) [![Coverage Status](https://coveralls.io/repos/github/USGS-R/ncdfgeom/badge.svg?branch=master)](https://coveralls.io/github/USGS-R/ncdfgeom?branch=master) [![CRAN Downloads](https://cranlogs.r-pkg.org/badges/grand-total/ncdfgeom)](https://cran.r-project.org/package=ncdfgeom) [![CRAN](https://www.r-pkg.org/badges/version/ncdfgeom)](https://cran.r-project.org/package=ncdfgeom)
+![R-CMD-check](https://github.com/usgs-r/ncdfgeom/workflows/R-CMD-check/badge.svg) [![codecov](https://codecov.io/gh/usgs-r/ncdfgeom/branch/master/graph/badge.svg?token=5c1L38yK5q)](https://codecov.io/gh/usgs-r/ncdfgeom) [![CRAN Downloads](https://cranlogs.r-pkg.org/badges/grand-total/ncdfgeom)](https://cran.r-project.org/package=ncdfgeom) [![CRAN](https://www.r-pkg.org/badges/version/ncdfgeom)](https://cran.r-project.org/package=ncdfgeom)
 
 `ncdfgeom` reads and writes geometry data (points lines and polygons), attributes of geometries, and time series associated with the geometries in a standards-compliant way.