The issue as the unit of work
The idea of running a project from a single GitHub Issue wasn't mine; marketing teams at GitHub already opened one per project, keeping plan, discussion and status together. What changed is that the issue now does the work rather than just recording it.
Three primitives carry the system:
- Issue forms as the application form. An issue form replaces the blank text box with structured fields — event title, date, region, campaign name, target audience. One form per event type, such as webinars and in-person events, all feeding the same machinery.
- Labels as switches. A label like
event-setupis a trigger, not a tag: each workflow only runs when it is present. - Actions as the machinery. GitHub Actions workflows fire on label events, parse the form fields out of the issue body and execute.
History, visibility, review and a URL for every decision come along for free. The prerequisite is narrower than it sounds: our event management platform exposes an API. Our CRM doesn't even need one — its official CLI covers everything, and no API key was ever configured because it signs in through the browser. API or CLI, the requirement is a scriptable way in, whether the tool is an event platform, a CRM, a form builder or an analytics service.
The obvious objection is reinvention — packaged marketing automation platforms exist. But APAC is less one market than a collection of different ones, and workflows shift per sub-region and segment: the same webinar may run in Japanese for Tokyo one month and Korean for Seoul the next, with different segments, different CRM fields and a different definition of a good lead. Making a packaged tool absorb those variations costs customization budgets, consulting hours and roadmap waiting. Building from what's at hand makes a workflow change a pull request: described, reviewed, merged on main.
Planning as a conversation
The pipeline starts before the Issue exists, when I tell GitHub Copilot something like: "I want to run a webinar about AI-assisted development in November."
What happens next is shaped by AGENTS.md at the repository root — a plain-Markdown team runbook defining campaign naming, how fiscal quarters map to dates, per-region time zones and what a good invitation email looks like. Copilot reads it, finds a similar past event, proposes a compliant campaign name, drafts two invitation emails and asks the questions the runbook specifies.
The conversation at the front of the pipeline is deliberate and solves two problems. Automate everything and you lose flexibility; let humans fill in everything and you reintroduce mistakes. Copilot follows the template, so the data landing in the Issue is the right data in the right format, and I can still bend details for one event without breaking anything downstream.
This started in GitHub Copilot CLI in a terminal — fine for me, a barrier for many people I want in this workflow. The GitHub Copilot app moves the same conversation into a desktop window, dropping the entry bar from "comfortable with a shell" to "can type."
The division of labor is the point: GitHub Copilot drafts; I decide. Every campaign name, subject line and date gets sign-off. At the end, Copilot files the Issue with the right labels — and the machines take over.
Staging a whole event from one label
When event-setup lands, a workflow does in minutes what took the better part of a day:
- Duplicates a past event on the event platform to create the new landing page
- Generates the full set of UTM-tagged URLs, one per channel, consistently formatted every time
- Produces the invitation email as a Word document and commits it to the repository
- Opens request Issues with the teams that send emails and track regional marketing
- Adds the event to project boards and fills in the fields
- Posts a summary comment back on the Issue so the next human sees everything in one place
Screening runs on a schedule rather than a label. Each morning a cron-triggered workflow fetches the latest registrants for every open event and shares the cleaned-up list. For invite-only events it also screens the waitlist against our criteria — developer at an enterprise account, student, or a competitor who would very much like to attend the executive briefing — before anyone is approved.
The design decision I'm most proud of is DRY_RUN, a repository variable every workflow checks before running. With it on, nothing external is touched: no landing pages, no issues in other repositories, no lists shared. A team of marketers automating its own job needs a way to rehearse, and this is the reason I was never afraid to experiment.
Post-event work as slash commands
Exporting attendees, reformatting columns for CRM upload, matching company names to account records and writing the report is now two commands. /lead-upload fetches the attendee list, shapes it into the exact format marketing operations needs, files the request Issue and closes out the tracking issues. /event-report pulls attendance metrics and survey results and posts the report as a comment on the event's Issue — the one URL where everything about that event lives.
Both are GitHub Copilot agent skills, and a skill is a Markdown file: a SKILL.md holding a procedure in prose that says what to do, in what order, and what to watch out for. Mine read like the runbooks I used to keep in my head, because that's what they are. If you can write a runbook, you can write a skill.
Skills are also the flexibility mechanism. No two markets in the Asia/Pacific (APAC) region run follow-up identically — audiences, segments and local conventions differ — and a hard-coded workflow would force every market into one shape. Procedures in Markdown let each market adapt the runbook without touching the machinery, which is why post-event steps live in skills rather than fixed pipelines. New skills arrive by pull request and are reviewed before merging, with a CODEOWNERS file routing review to a maintainer. Governance came free with the platform.
Guardrails, human and platform
I automated a workflow that touches customer data and API credentials, in a repository the whole team can see. What made that safe wasn't restraint on my part:
- Secret scanning with push protection. The nightmare is committing an API token. GitHub's push protection blocks the push before the secret lands, and GitHub's own tokens are revoked automatically even if one slips through.
- Copilot data policies. Registrant lists are business data, and fixed scripts handle them in fixed ways — but real work never stays entirely fixed, and some days need a one-off cut no script anticipates. Because Copilot's business plans don't retain prompts or train on them, that analysis can be asked for directly instead of pasting business data into whatever consumer chatbot is open in the next tab. Organization policy, not personal judgment, sets which models are usable, so even a one-off experiment stays inside decided boundaries.
The guardrails I built myself — DRY_RUN, a test suite on every pull request, code review on every change — are standard developer habits that protect marketing work just as well. The skills added something else: because each procedure is a named, fixed unit of work, the model can be matched to the job from the approved lineup, a fast inexpensive one for daily list cleaning and a stronger one for campaign copy.
One honest failure worth repeating: the morning screening workflow once failed silently for five days before anyone noticed the lists had gone stale. Give every scheduled workflow a way to complain loudly.
Shipping the first automation
The practical starting point is the single most repetitive task in your week. Before writing anything, check whether the tools that task touches expose an API or a CLI — the answer is often yes, and more often than expected.
From there, build the smallest version that works: an issue form to capture the inputs, a label that acts as the trigger, and an Action that performs one step. The alternative is to write the runbook itself as a SKILL.md and let GitHub Copilot execute it. Either way, run it with a dry-run switch until you trust the output, then grow it.
The work being automated doesn't have to be code you authored. Documenting how a process already runs is enough for the platform to take it from there — a written-down routine, not a new system, is the distance between manual execution and automation.
Starting points:



