Including the optioned for a more detailed resume as well

This commit is contained in:
Mike Eberlein 2026-05-10 16:06:05 -04:00
parent 71fda409e7
commit f41a059b8d
13 changed files with 367 additions and 62 deletions

View File

@ -2,41 +2,77 @@
#
# Single content source: resume.yaml
#
# make -> PDF (default; renders .tex from YAML, then pdflatex twice)
# make odt -> ODT (renders directly from YAML)
# make docx -> DOCX (ODT -> LibreOffice convert -> DOCX)
# make all -> PDF + ODT + DOCX
# make clean -> remove TeX aux files
# make distclean -> also remove generated PDF/ODT/DOCX/TEX
# Two flavors:
# short -> condensed, single-page (default outputs)
# full -> detailed, longer (Detailed.* outputs)
#
# make -> short PDF
# make odt -> short ODT
# make docx -> short DOCX
# make short -> short PDF + ODT + DOCX
# make detailed -> detailed PDF + ODT + DOCX
# make all -> short and detailed in every format
# make clean -> remove TeX aux files
# make distclean -> also remove every generated PDF/ODT/DOCX/TEX
YAML := resume.yaml
# Short (condensed) outputs
TEX := MikeEberlein_Resume.tex
PDF := MikeEberlein_Resume.pdf
ODT := MikeEberlein_Resume.odt
DOCX := MikeEberlein_Resume.docx
.PHONY: all pdf odt docx clean distclean
# Detailed outputs
TEX_D := MikeEberlein_Resume_Detailed.tex
PDF_D := MikeEberlein_Resume_Detailed.pdf
ODT_D := MikeEberlein_Resume_Detailed.odt
DOCX_D := MikeEberlein_Resume_Detailed.docx
all: $(PDF) $(ODT) $(DOCX)
# Every artifact is .PHONY so `make` always rebuilds from resume.yaml — same
# effect as `make -B`. Resume builds are fast; correctness > caching.
.PHONY: all short detailed pdf odt docx clean distclean \
$(TEX) $(PDF) $(ODT) $(DOCX) \
$(TEX_D) $(PDF_D) $(ODT_D) $(DOCX_D)
all: short detailed
short: $(PDF) $(ODT) $(DOCX)
detailed: $(PDF_D) $(ODT_D) $(DOCX_D)
pdf: $(PDF)
odt: $(ODT)
docx: $(DOCX)
# ---------- short ----------
$(TEX): $(YAML) render_tex.py
python3 render_tex.py
python3 render_tex.py --level=short --output=$(TEX)
$(PDF): $(TEX)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX)
$(ODT): $(YAML) render_odt.py
python3 render_odt.py
python3 render_odt.py --level=short --output=$(ODT)
$(DOCX): $(ODT)
soffice --headless --convert-to docx $(ODT)
# ---------- detailed ----------
$(TEX_D): $(YAML) render_tex.py
python3 render_tex.py --level=full --output=$(TEX_D)
$(PDF_D): $(TEX_D)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX_D)
pdflatex -interaction=nonstopmode -halt-on-error $(TEX_D)
$(ODT_D): $(YAML) render_odt.py
python3 render_odt.py --level=full --output=$(ODT_D)
$(DOCX_D): $(ODT_D)
soffice --headless --convert-to docx $(ODT_D)
# ---------- maintenance ----------
clean:
rm -f *.aux *.log *.out *.toc *.fls *.fdb_latexmk *.synctex.gz
distclean: clean
rm -f $(PDF) $(ODT) $(DOCX) $(TEX)
rm -f $(PDF) $(ODT) $(DOCX) $(TEX) $(PDF_D) $(ODT_D) $(DOCX_D) $(TEX_D)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -89,6 +89,7 @@ Engineering manager with 15+ years building market-leading automotive infotainme
\subrole{Infotainment Vehicle Data}{2023 Present}
\begin{subbullets}
\item Lead software engineers delivering the mechanisms that surface vehicle data from in-vehicle modules to applications and services across Android, Yocto Linux, and QNX.
\item Manage performance, headcount and workload commitment
\end{subbullets}
\subrole{Development Quality Assurance}{2021 2023}
@ -103,7 +104,7 @@ Engineering manager with 15+ years building market-leading automotive infotainme
\subrole{Business Manager}{2021 2023}
\begin{subbullets}
\item Owned and defended the platform org budget; ran SOWs with multiple suppliers in partnership with procurement; built workload models and managed headcount allocation.
\item Owned and defended the platform org budget; ran statements of work with multiple suppliers in partnership with procurement; built workload models and managed headcount allocation.
\end{subbullets}
\role{Infotainment Software Program Manager}{Jan 2017 May 2021}
@ -130,7 +131,7 @@ Engineering manager with 15+ years building market-leading automotive infotainme
\role{Software Verification Engineer / UI Developer}{Oct 2008 Mar 2011}
\begin{bullets}
\item Converted Photoshop design files into ActionScript 2 UI components consumed by engineering teams.
\item Authored automated test tools using VB.NET, CAN, ACV-LAN, and proprietary trace tools; analyzed requirements, ran in-vehicle test drives, and validated infotainment systems with customers.
\item Authored automated test tools using VB.NET and proprietary trace tools; analyzed requirements, ran in-vehicle test drives, and validated infotainment systems with customers.
\end{bullets}
\section{Education}\sectionrule

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,148 @@
% Mike Eberlein — single-page resume (generated from resume.yaml).
% Build: pdflatex MikeEberlein_Resume.tex (run twice for stable layout)
% Do not edit by hand — re-run `python3 render_tex.py` after changing resume.yaml.
%
% Fonts: Roboto via the roboto LaTeX package (texlive-fonts-extra). The official
% Google Roboto font repo (with OFL license) is also bundled at ./fonts/ —
% individual weights live in ./fonts/static/, variable fonts at ./fonts/.
\documentclass[letterpaper,10pt]{extarticle}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[sfdefault]{roboto}
\usepackage{microtype}
\DisableLigatures{encoding = *, family = *} % keep fi/fl as two letters so PDF text search / ATS works
\usepackage[letterpaper,margin=0.5in,top=0.35in,bottom=0.3in]{geometry}
\usepackage[dvipsnames]{xcolor}
\usepackage{titlesec}
\usepackage{enumitem}
\usepackage{hyperref}
\usepackage{ragged2e}
\usepackage{parskip}
\newcommand{\RobotoLight}{\fontseries{l}\selectfont}
\newcommand{\RobotoMedium}{\fontseries{m}\selectfont}
\definecolor{accent}{HTML}{1F3864}
\definecolor{body}{HTML}{222222}
\definecolor{muted}{HTML}{555555}
\color{body}
\hypersetup{colorlinks=true, urlcolor=accent, linkcolor=accent}
\setlength{\parindent}{0pt}
\setlength{\parskip}{0pt}
\linespread{1.0}
\pagestyle{empty}
\titleformat{\section}
{\color{accent}\RobotoMedium\bfseries\large}
{}{0pt}
{\MakeUppercase}
\titlespacing*{\section}{0pt}{4pt}{0pt}
\newcommand{\sectionrule}{\vspace{-4pt}{\color{accent}\rule{\linewidth}{0.5pt}}\par\vspace{1pt}}
\newcommand{\job}[2]{%
\vspace{3pt}%
\noindent\textbf{#1}\hfill\textbf{#2}\par\vspace{0pt}%
}
\newcommand{\role}[2]{%
\vspace{1pt}%
\noindent\textit{\textcolor{muted}{#1}}\hfill\textit{\textcolor{muted}{#2}}\par%
}
\newcommand{\subrole}[2]{%
\vspace{1pt}%
\noindent\hspace{0.18in}#1\hfill\textit{\textcolor{muted}{#2}}\par%
}
\newlist{bullets}{itemize}{2}
\setlist[bullets]{leftmargin=0.22in, itemsep=0pt, topsep=0pt, parsep=0pt, label={\textbullet}}
\newlist{subbullets}{itemize}{2}
\setlist[subbullets]{leftmargin=0.42in, itemsep=0pt, topsep=0pt, parsep=0pt, label={\textbullet}, before=\color{muted}}
\newcommand{\name}[1]{%
\begin{center}%
{\color{accent}\fontseries{l}\fontsize{26}{30}\selectfont #1}%
\end{center}%
\vspace{10pt}%
}
\newcommand{\contact}[1]{%
\begin{center}\textcolor{muted}{\small #1}\end{center}%
\vspace{2pt}%
}
\begin{document}
\name{MIKE EBERLEIN}
\contact{Engineering Manager • Infotainment \& Software-Defined Vehicles \textbullet{} \href{mailto:mike.t.eberlein@gmail.com}{mike.t.eberlein@gmail.com}}
{\justifying\noindent
Engineering manager with 15+ years building market-leading automotive infotainment systems, spanning manual and automated test, UI development, embedded service development, program management, and people leadership. Effective at translating ambiguous platform goals into shippable software across Android, Yocto Linux, and QNX, and at growing teams that deliver on aggressive vehicle-program timing.\par}
\section{Experience}\sectionrule
\job{General Motors}{Oct 2014 Present}
\role{Engineering Group Manager}{May 2021 Present}
\subrole{Infotainment Vehicle Data}{2023 Present}
\begin{subbullets}
\item Lead software engineers delivering the mechanisms that surface vehicle data from in-vehicle modules to applications and services across Android, Yocto Linux, and QNX.
\item Manage performance, headcount and workload commitment
\end{subbullets}
\subrole{Development Quality Assurance}{2021 2023}
\begin{subbullets}
\item Led a cross-functional team of 20+ engineers driving functional test for infotainment platform development; established cross-component knowledge sharing and team planning practices.
\end{subbullets}
\subrole{Ultifi Platform \& Vehicle Data}{2021 2023}
\begin{subbullets}
\item Led development of core embedded components for GM's software-defined vehicle platform, partnering with architecture, systems, and downstream test to drive end-to-end delivery.
\end{subbullets}
\subrole{Business Manager}{2021 2023}
\begin{subbullets}
\item Owned and defended the platform org budget; ran statements of work with multiple suppliers in partnership with procurement; built workload models and managed headcount allocation.
\end{subbullets}
\role{Infotainment Software Program Manager}{Jan 2017 May 2021}
\begin{bullets}
\item Lead software program manager for MY22/MY23 Center Stack Module (CSM) development — owned software delivery, timing, and scope from program initiation through late vehicle milestones.
\item Drove impact analysis, feature commitment, and delivery tracking with partner teams across GM; managed Tier-X suppliers on deliveries, defects, and change negotiations.
\item MY20MY23 program execution commitment lead: scoped and estimated new features in concept phase, then tracked scope and staffing through development.
\item Built Python 3 / Excel / Rational Team Concert API tooling for task breakdown, inter-team dependencies, and historical-data-driven staffing models.
\end{bullets}
\role{Infotainment Software Engineer}{Oct 2014 Jan 2017}
\begin{bullets}
\item Developed Android (Java) infotainment apps including a hybrid powertrain optimization HMI and the USB / over-the-air software update client for the head unit.
\item Built Windows-based developer tooling with CAN simulation to enable powertrain teams to iterate against the infotainment system off-vehicle.
\end{bullets}
\job{Harman International}{Oct 2008 Oct 2014}
\role{Software Engineer}{Mar 2011 Oct 2014}
\begin{bullets}
\item Designed and built navigation infotainment applications in ActionScript 2/3, Lua, and C++ on QNX-based head units shipped to multiple OEMs.
\item Managed the navigation engine supplier — deliveries, feature implementation, and defect resolution — and built Excel-based dashboards over the internal defect database for program-level reporting.
\end{bullets}
\role{Software Verification Engineer / UI Developer}{Oct 2008 Mar 2011}
\begin{bullets}
\item Converted Photoshop design files into ActionScript 2 UI components consumed by engineering teams.
\item Authored automated test tools using VB.NET and proprietary trace tools; analyzed requirements, ran in-vehicle test drives, and validated infotainment systems with customers.
\end{bullets}
\section{Education}\sectionrule
\job{B.S. Computer Science, Lawrence Technological University}{Apr 2011}
\begin{bullets}
\item Graduated summa cum laude from the Honors College. Coursework in C, C++, Java, VB.net, mobile development, and scripting.
\end{bullets}
\section{Certifications}\sectionrule
Certified Scrum Professional (20122015) \textbullet{} Certified Scrum Master (20102019) \textbullet{} SAFe Agilist (20202023)
\end{document}

View File

@ -4,6 +4,11 @@ Single-page resume for Mike Eberlein (Engineering Manager — automotive infotai
**Single content source: `resume.yaml`.** Two renderers (LaTeX and ODT) read the YAML and emit format-specific files. DOCX is produced by converting the ODT with LibreOffice. Edit `resume.yaml`; the generated `.tex` should not be edited by hand.
Two flavors are produced from the same YAML:
- **Short** — condensed single-page resume. Outputs: `MikeEberlein_Resume.{tex,pdf,odt,docx}`.
- **Detailed** — longer version with extra bullets / roles / jobs. Outputs: `MikeEberlein_Resume_Detailed.{tex,pdf,odt,docx}`.
## Files
| File | Purpose |
@ -21,12 +26,21 @@ Single-page resume for Mike Eberlein (Engineering Manager — automotive infotai
## Build
```bash
make # PDF (default)
make odt # ODT
make docx # DOCX (via LibreOffice from the ODT)
make all # PDF + ODT + DOCX
make clean # remove TeX aux files
make distclean # also remove generated PDF/ODT/DOCX/TEX
make # short PDF (default)
make odt # short ODT
make docx # short DOCX
make short # short PDF + ODT + DOCX
make detailed # detailed PDF + ODT + DOCX
make all # both flavors, every format
make clean # remove TeX aux files
make distclean # also remove generated PDF/ODT/DOCX/TEX
```
Run the renderers directly if you want a custom output path:
```bash
python3 render_tex.py --level=full --output=foo.tex
python3 render_odt.py --level=short --output=foo.odt
```
Required system packages (Debian/Ubuntu):
@ -59,7 +73,29 @@ education:
certifications: [ ... ]
```
After editing, run `make all` to rebuild every format from the same content.
### Short vs. Detailed
Any list field above can have a sibling list with the `_full` suffix. The base list always renders. The `_full` list is appended only in `--level=full`. Examples:
```yaml
bullets: # always shown
- Short bullet.
bullets_full: # appended in detailed only
- Extra detail bullet.
subroles:
- { title: Always-shown sub-role, ... }
subroles_full:
- { title: Detailed-only sub-role, ... }
experience: [ ... ]
experience_full: # an entire extra job, only in detailed
- { company: ..., dates: ..., roles: [ ... ] }
```
Same convention works on `roles_full`, `education_full`, `certifications_full`.
After editing, `make all` rebuilds both flavors in every format from the same YAML.
## Layout / styling

View File

@ -1,21 +1,28 @@
#!/usr/bin/env python3
"""Render resume.yaml -> MikeEberlein_Resume.odt.
"""Render resume.yaml -> a .odt file.
Two output flavors:
--level=short (default) -> condensed single-page resume.
--level=full -> detailed resume; concatenates each list with its
`_full` sibling (e.g. bullets + bullets_full).
Builds the ODT zip from scratch (mimetype, manifest, meta, styles, content).
The ODT styling lives inline as STYLES below; content comes from resume.yaml.
DOCX is produced by piping this output through LibreOffice:
soffice --headless --convert-to docx MikeEberlein_Resume.odt
soffice --headless --convert-to docx <file>.odt
"""
import argparse
import os
import shutil
import sys
import yaml
import zipfile
HERE = os.path.dirname(os.path.abspath(__file__))
DATA = os.path.join(HERE, "resume.yaml")
OUT = os.path.join(HERE, "MikeEberlein_Resume.odt")
DEFAULT_OUT = {
"short": os.path.join(HERE, "MikeEberlein_Resume.odt"),
"full": os.path.join(HERE, "MikeEberlein_Resume_Detailed.odt"),
}
MIMETYPE = "application/vnd.oasis.opendocument.text"
@ -167,7 +174,14 @@ def bullet(text, style="Bullet"):
f'<text:p text:style-name="{style}">{xesc(text)}</text:p>'
f'</text:list-item></text:list>')
def render(data) -> str:
def merged(item, key, level):
"""Return item[key] for short, or item[key] + item[key + '_full'] for full."""
base = item.get(key) or []
if level == "full":
base = list(base) + list(item.get(key + "_full") or [])
return base
def render(data, level="short") -> str:
parts = []
h = data["header"]
parts.append(p("Name", xesc(h["name"])))
@ -176,36 +190,44 @@ def render(data) -> str:
parts.append(p("Summary", xesc(data["summary"].strip())))
parts.append(p("SectionHead", "EXPERIENCE"))
for company in data["experience"]:
for company in merged(data, "experience", level):
parts.append(f'<text:p text:style-name="JobTab">{b(company["company"])}{TAB}{xesc(company["dates"])}</text:p>')
for role in company["roles"]:
for role in merged(company, "roles", level):
parts.append(f'<text:p text:style-name="RoleTab">{i(role["title"])}{TAB}{i(role["dates"])}</text:p>')
if "subroles" in role:
for sr in role["subroles"]:
subroles = merged(role, "subroles", level)
if subroles:
for sr in subroles:
parts.append(f'<text:p text:style-name="SubRoleTab">{xesc(sr["title"])}{TAB}{i(sr["dates"])}</text:p>')
for blt in sr["bullets"]:
for blt in merged(sr, "bullets", level):
parts.append(bullet(blt, style="SubBullet"))
elif "bullets" in role:
for blt in role["bullets"]:
else:
for blt in merged(role, "bullets", level):
parts.append(bullet(blt, style="Bullet"))
parts.append(p("SectionHead", "EDUCATION"))
for ed in data["education"]:
for ed in merged(data, "education", level):
parts.append(f'<text:p text:style-name="JobTab">{b(ed["school"])}{TAB}{xesc(ed["dates"])}</text:p>')
for blt in ed["bullets"]:
for blt in merged(ed, "bullets", level):
parts.append(bullet(blt, style="Bullet"))
parts.append(p("SectionHead", "CERTIFICATIONS"))
parts.append(p("Standard", " &#8226; ".join(xesc(c) for c in data["certifications"])))
parts.append(p("Standard", " &#8226; ".join(xesc(c) for c in merged(data, "certifications", level))))
return CONTENT_HEAD + "".join(parts) + CONTENT_TAIL
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--level", choices=["short", "full"], default="short")
ap.add_argument("--output", default=None,
help="Output .odt path (default: MikeEberlein_Resume.odt / MikeEberlein_Resume_Detailed.odt)")
args = ap.parse_args()
out_path = args.output or DEFAULT_OUT[args.level]
with open(DATA, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
content = render(data)
content = render(data, level=args.level)
with zipfile.ZipFile(OUT, "w", zipfile.ZIP_DEFLATED) as z:
with zipfile.ZipFile(out_path, "w", zipfile.ZIP_DEFLATED) as z:
zi = zipfile.ZipInfo("mimetype")
zi.compress_type = zipfile.ZIP_STORED
z.writestr(zi, MIMETYPE)
@ -213,7 +235,7 @@ def main():
z.writestr("meta.xml", META)
z.writestr("styles.xml", STYLES)
z.writestr("content.xml", content)
print(f"wrote {OUT}")
print(f"wrote {out_path} (level={args.level})")
if __name__ == "__main__":
main()

View File

@ -1,17 +1,24 @@
#!/usr/bin/env python3
"""Render resume.yaml -> MikeEberlein_Resume.tex.
"""Render resume.yaml -> a .tex file.
Two output flavors are supported:
--level=short (default) -> condensed single-page resume.
--level=full -> detailed resume; concatenates each list with its
`_full` sibling (e.g. bullets + bullets_full).
The LaTeX preamble (styles, macros, page layout) lives inline as PREAMBLE
below; if you want to tweak typography or colors, edit there. Content is read
from resume.yaml.
below; tweak typography or colors there. Content is read from resume.yaml.
"""
import argparse
import os
import sys
import yaml
HERE = os.path.dirname(os.path.abspath(__file__))
DATA = os.path.join(HERE, "resume.yaml")
OUT = os.path.join(HERE, "MikeEberlein_Resume.tex")
DEFAULT_OUT = {
"short": os.path.join(HERE, "MikeEberlein_Resume.tex"),
"full": os.path.join(HERE, "MikeEberlein_Resume_Detailed.tex"),
}
PREAMBLE = r"""% Mike Eberlein — single-page resume (generated from resume.yaml).
% Build: pdflatex MikeEberlein_Resume.tex (run twice for stable layout)
@ -108,6 +115,13 @@ def tex_escape(s: str) -> str:
out.append(LATEX_ESCAPES.get(ch, ch))
return "".join(out)
def merged(item, key, level):
"""Return item[key] for short, or item[key] + item[key + '_full'] for full."""
base = item.get(key) or []
if level == "full":
base = list(base) + list(item.get(key + "_full") or [])
return base
def emit_bullets(items, env="bullets"):
lines = [f"\\begin{{{env}}}"]
for b in items:
@ -115,7 +129,7 @@ def emit_bullets(items, env="bullets"):
lines.append(f"\\end{{{env}}}")
return "\n".join(lines)
def render(data) -> str:
def render(data, level="short") -> str:
out = [PREAMBLE, ""]
out.append(r"\begin{document}")
out.append("")
@ -132,39 +146,49 @@ def render(data) -> str:
out.append("")
out.append(r"\section{Experience}\sectionrule")
out.append("")
for company in data["experience"]:
for company in merged(data, "experience", level):
out.append(f"\\job{{{tex_escape(company['company'])}}}{{{tex_escape(company['dates'])}}}")
for role in company["roles"]:
for role in merged(company, "roles", level):
out.append(f"\\role{{{tex_escape(role['title'])}}}{{{tex_escape(role['dates'])}}}")
if "subroles" in role:
subroles = merged(role, "subroles", level)
if subroles:
out.append("")
for sr in role["subroles"]:
for sr in subroles:
out.append(f"\\subrole{{{tex_escape(sr['title'])}}}{{{tex_escape(sr['dates'])}}}")
out.append(emit_bullets(sr["bullets"], env="subbullets"))
out.append(emit_bullets(merged(sr, "bullets", level), env="subbullets"))
out.append("")
else:
bullets = merged(role, "bullets", level)
if bullets:
out.append(emit_bullets(bullets, env="bullets"))
out.append("")
elif "bullets" in role:
out.append(emit_bullets(role["bullets"], env="bullets"))
out.append("")
out.append(r"\section{Education}\sectionrule")
out.append("")
for ed in data["education"]:
for ed in merged(data, "education", level):
out.append(f"\\job{{{tex_escape(ed['school'])}}}{{{tex_escape(ed['dates'])}}}")
out.append(emit_bullets(ed["bullets"], env="bullets"))
out.append(emit_bullets(merged(ed, "bullets", level), env="bullets"))
out.append("")
out.append(r"\section{Certifications}\sectionrule")
out.append("")
out.append(" \\textbullet{} ".join(tex_escape(c) for c in data["certifications"]))
out.append(" \\textbullet{} ".join(tex_escape(c) for c in merged(data, "certifications", level)))
out.append("")
out.append(r"\end{document}")
return "\n".join(out) + "\n"
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--level", choices=["short", "full"], default="short")
ap.add_argument("--output", default=None,
help="Output .tex path (default: MikeEberlein_Resume.tex / MikeEberlein_Resume_Detailed.tex)")
args = ap.parse_args()
out_path = args.output or DEFAULT_OUT[args.level]
with open(DATA, "r", encoding="utf-8") as f:
data = yaml.safe_load(f)
tex = render(data)
with open(OUT, "w", encoding="utf-8") as f:
tex = render(data, level=args.level)
with open(out_path, "w", encoding="utf-8") as f:
f.write(tex)
print(f"wrote {OUT}")
print(f"wrote {out_path} (level={args.level})")
if __name__ == "__main__":
main()

View File

@ -1,6 +1,20 @@
# Single source of truth for the resume content.
# Renderers read this and emit MikeEberlein_Resume.tex and MikeEberlein_Resume.odt.
# Renderers read this and emit:
# MikeEberlein_Resume.{tex,odt} (short, condensed single-page)
# MikeEberlein_Resume_Detailed.{tex,odt} (full, longer version)
# Edit content here; layout/styling lives in the renderers.
#
# SHORT vs. FULL CONVENTION:
# Any list field can have a sibling list with the `_full` suffix. The base
# list always renders. The `_full` list is appended only in --level=full.
# This works at every level:
# bullets / bullets_full (within a role, subrole, or education entry)
# subroles / subroles_full (under a role)
# roles / roles_full (under a company)
# experience / experience_full (top level — extra jobs only in full)
# education / education_full
# certifications / certifications_full
# See the few `*_full:` keys below for examples; add or remove freely.
header:
name: MIKE EBERLEIN
@ -26,6 +40,11 @@ experience:
dates: 2023 Present
bullets:
- Lead software engineers delivering the mechanisms that surface vehicle data from in-vehicle modules to applications and services across Android, Yocto Linux, and QNX.
- Manage performance, headcount and workload commitment
bullets_full:
# Extra bullets that only appear in the detailed resume.
# - Drove migration of the legacy CAN-signal pipeline to <xyz> with <result>.
# - Mentored N engineers; ran weekly arch reviews.
- title: Development Quality Assurance
dates: 2021 2023
bullets:
@ -37,7 +56,7 @@ experience:
- title: Business Manager
dates: 2021 2023
bullets:
- Owned and defended the platform org budget; ran SOWs with multiple suppliers in partnership with procurement; built workload models and managed headcount allocation.
- Owned and defended the platform org budget; ran statements of work with multiple suppliers in partnership with procurement; built workload models and managed headcount allocation.
- title: Infotainment Software Program Manager
dates: Jan 2017 May 2021
@ -52,9 +71,17 @@ experience:
bullets:
- Developed Android (Java) infotainment apps including a hybrid powertrain optimization HMI and the USB / over-the-air software update client for the head unit.
- Built Windows-based developer tooling with CAN simulation to enable powertrain teams to iterate against the infotainment system off-vehicle.
bullets_full:
# Add detail-only bullets here.
# - Specific projects, technologies, results.
- company: Harman International
dates: Oct 2008 Oct 2014
# Example: roles_full would add additional roles only in the detailed resume.
# roles_full:
# - title: Some Role Only Listed In Full
# dates: ...
# bullets: [...]
roles:
- title: Software Engineer
dates: Mar 2011 Oct 2014
@ -66,7 +93,7 @@ experience:
dates: Oct 2008 Mar 2011
bullets:
- Converted Photoshop design files into ActionScript 2 UI components consumed by engineering teams.
- Authored automated test tools using VB.NET, CAN, ACV-LAN, and proprietary trace tools; analyzed requirements, ran in-vehicle test drives, and validated infotainment systems with customers.
- Authored automated test tools using VB.NET and proprietary trace tools; analyzed requirements, ran in-vehicle test drives, and validated infotainment systems with customers.
education:
- school: B.S. Computer Science, Lawrence Technological University
@ -78,3 +105,14 @@ certifications:
- Certified Scrum Professional (20122015)
- Certified Scrum Master (20102019)
- SAFe Agilist (20202023)
# certifications_full:
# - Add any certs you'd only list on the detailed resume here.
# Example of an entire extra job for the detailed resume only:
# experience_full:
# - company: Some Earlier Employer
# dates: ...
# roles:
# - title: ...
# dates: ...
# bullets: [...]