MyRain - WordPad

Case study 03 / Automation / 2026

MyRain price sync

A weekly pricing chore across about 1,000 SKUs, handed over to Python.

A Python integration between a supplier portal and Shopify, built to replace a manual weekly pricing workflow across about 1,000 product SKUs.

~1,000product SKUs

Role, status and stack
Role
Sole developer (Software Developer, Volunteer)
Status
Engagement ran Apr 2026 to Aug 2026. Deployed and scheduled through GitHub Actions
Made with
Python / Playwright / openpyxl / Shopify GraphQL Admin API / GitHub Actions / pytest

The problem

The tedium was obvious. The real risk was a $3 part going live at $1,000.

MyRain is a small irrigation business on Shopify. Every week, about 1,000 prices got checked by hand: download the supplier's list, compare it with the store, key in the differences. Some supplier prices use a different unit or pack size than the store sells, so one bad match could reach the live store. I worked through the process and its risks with the owner, then built around them.

A terminal showing a dry-run summary: 229 prices to update, 71 unchanged, 197 not found, 28 flagged, 0 errors.

Output from the file-driven version's dry run on November 4, 2026. The file name is changed, and the per-product lines are left out.

The system

MyRain price sync: Download, then Parse, then Match SKUs, then Validate, then Update Shopify, then Report. Choose a step for details. All steps are also listed under the diagram.

Download. Playwright logs in to the supplier portal and downloads the Excel price list.

What can go wrong: Retries up to three times, then stops with a clear error before anything touches Shopify.

Read all 6 steps at once
  1. Download. Playwright logs in to the supplier portal and downloads the Excel price list. What can go wrong: Retries up to three times, then stops with a clear error before anything touches Shopify.
  2. Parse. openpyxl finds the SKU and retail price columns and builds a clean price map. What can go wrong: No columns, no run. Unreadable prices are skipped and logged, and duplicate SKUs raise a warning.
  3. Match SKUs. Pulls every Shopify variant through GraphQL and matches it to the list by normalized SKU. What can go wrong: Store products that aren't on the price list are counted and left alone.
  4. Validate. Keeps only real changes. A cent or less counts as unchanged. What can go wrong: In test mode, the run stops here and logs what would change.
  5. Update Shopify. Sends changes in batches of 25, slowing down as the rate limit budget runs low. What can go wrong: A rejected update fails the whole run, so it can't go unnoticed.
  6. Report. Writes JSON logs and an execution report, kept as GitHub Actions artifacts. What can go wrong: A crashed run still writes a failure report, and GitHub emails the repository owner.
Test mode
--dry-run does the whole comparison and stops before writing anything. --local-file skips the portal login, so a price list can be tested on its own.
A pytest suite
44 tests cover the parser, Shopify client and sync engine with mocked HTTP and fixture Excel files, so they need no live credentials.
Scheduling
A GitHub Actions workflow is scheduled for Mondays at 10:00 UTC, and can be started by hand, with or without test mode.
Replaceable source
Only the extractor knows where prices come from. If the supplier ever offers a direct feed, that one piece changes.
An outlier guard
A file-driven version flags and skips any change over 50%, with the percentage in its report. Those are usually unit mismatches, like per-foot against per-roll, and look exactly like real changes until a person checks.
Credentials
Credentials live in GitHub Actions secrets, never the source code. The Shopify client uses a short-lived token and refreshes it when needed.
Operating procedures
Step-by-step procedures for non-technical staff, so running it doesn't depend on me.

Results

GitHub Actions schedule
Weekly
pytest tests
44
One real dry run of the file-driven version, November 4, 2026
ResultSKUs
Loaded from export525
Would update229
Unchanged71
Not found in Shopify197
Flagged as outliers28
Errors0
A dry run against the live store with a June 2026 supplier export. Nothing was written, and product data is left out. 197 SKUs not found is exactly the kind of number you want to see before an update, not after.

What I learned

What I learned

I underestimated the run report. Nobody asks for it until the week a price looks wrong, then it's all anyone wants. Most of the work in a small automation is deciding what it should refuse to do.

What I'd do differently

Ask for a direct supplier feed early, since a browser login is the part most likely to break when a page changes. And build the outlier guard into the first version, not after seeing what the data could do.

Built with an AI coding assistant. I set the requirements with the owner, decided the safeguards and what counted as a bad update, and did the debugging and checking.

Properties

Type
Automation
Role
Sole developer (Software Developer, Volunteer)
Year
2026
Stack
Python, Playwright, openpyxl, Shopify GraphQL Admin API, GitHub Actions, pytest
Status
Engagement ran Apr 2026 to Aug 2026. Deployed and scheduled through GitHub Actions
Case study, about 2 min read2026