I just do this manually: run
Uto mark available upgrades, then review to decide if there are any I don't want to pick up. Then
x to upgrade. I do this pretty regularly, and often check what's new at the same time. I've got a couple tweaks to simplify this (see below).
I suspect upgrading could be automated, but you do want to consider the case where an update breaks something and you need to back it out and then prevent your automated updater from just installing it again.
Some package menu tweaks:
(defun package-menu-find-marks ()
"Find packages marked for action in *Packages*."
;; Only in Emacs 25.1+
(defun package-menu-filter-by-status (status)
"Filter the *Packages* buffer by status."
"Status: " '("new" "installed" "dependency" "obsolete"))))
(package-menu-filter (concat "status:" status)))
(define-key package-menu-mode-map "s" #'package-menu-filter-by-status)
(define-key package-menu-mode-map "a" #'package-menu-find-marks)
With this I can use
s new to just see what packages are newly available. And after hitting
U to mark upgrades I can hit
a for an occur buffer list of the ones that were marked, in case I want to dig in to details of what changed etc.