Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .eslintignore

This file was deleted.

16 changes: 8 additions & 8 deletions .github/workflows/build-production.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
platforms: ${{ matrix.platform }}
Expand All @@ -49,7 +49,7 @@ jobs:
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: digest-production-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
path: /tmp/digests/*
Expand All @@ -65,17 +65,17 @@ jobs:

steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
path: /tmp/digests
pattern: digest-production-*
merge-multiple: true

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
16 changes: 8 additions & 8 deletions .github/workflows/build-staging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,21 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6
with:
context: .
platforms: ${{ matrix.platform }}
Expand All @@ -49,7 +49,7 @@ jobs:
touch "/tmp/digests/${digest#sha256:}"

- name: Upload digest
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
with:
name: digest-staging-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }}
path: /tmp/digests/*
Expand All @@ -65,17 +65,17 @@ jobs:

steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
with:
path: /tmp/digests
pattern: digest-staging-*
merge-multiple: true

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3

- name: Log in to GHCR
uses: docker/login-action@v3
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3
with:
registry: ghcr.io
username: ${{ github.actor }}
Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/pr-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: PR CI

on:
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review

permissions:
contents: read

concurrency:
group: pr-ci-${{ github.event.pull_request.number }}
cancel-in-progress: true

jobs:
validate:
if: ${{ !github.event.pull_request.draft }}
runs-on: ubuntu-latest
timeout-minutes: 20
env:
NEXT_TELEMETRY_DISABLED: 1

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Enable Corepack
run: corepack enable

- name: Set up Node.js
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6
with:
node-version-file: .nvmrc
cache: yarn
cache-dependency-path: yarn.lock

- name: Install dependencies
run: yarn install --immutable

- name: Lint JS/TS
run: yarn lint

- name: Lint CSS
run: yarn lint:css

- name: Run tests
run: yarn test --ci --watch=false

- name: Build
run: yarn build
99 changes: 86 additions & 13 deletions .github/workflows/staging-auto-pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,91 @@ on:

jobs:
pull-request:
name: Open PR to main
name: Open or Update PR to Production
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
concurrency:
group: staging-auto-pr
cancel-in-progress: true
steps:
- uses: actions/checkout@v2
name: checkout

- uses: repo-sync/pull-request@v2
name: pull-request
with:
destination_branch: "production"
pr_title: "Staging to Production"
pr_body: "This PR was auto-generated via a workflow action."
pr_reviewer: ${{ github.actor }}
source_branch: "staging"
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Create or update staging -> production PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
OWNER: ${{ github.repository_owner }}
SOURCE_BRANCH: staging
DESTINATION_BRANCH: production
PR_TITLE: Staging to Production
REVIEWER: ${{ github.actor }}
run: |
set -euo pipefail

compare_json="$(gh api "repos/${REPO}/compare/${DESTINATION_BRANCH}...${SOURCE_BRANCH}")"
compare_url="$(echo "${compare_json}" | jq -r '.html_url')"
ahead_by="$(echo "${compare_json}" | jq -r '.ahead_by')"

prs_tsv="$(mktemp)"
while IFS= read -r sha; do
[ -n "${sha}" ] || continue
gh api "repos/${REPO}/commits/${sha}/pulls" \
--jq '.[] | select(.merged_at != null) | "\(.number)\t\(.title)\t\(.html_url)"' \
>> "${prs_tsv}" || true
done < <(echo "${compare_json}" | jq -r '.commits[].sha')

if [ -s "${prs_tsv}" ]; then
prs_markdown="$(sort -t $'\t' -k1,1n -u "${prs_tsv}" | awk -F '\t' '{printf "- #%s %s (%s)\n", $1, $2, $3}')"
else
prs_markdown="- No linked pull requests found (direct commits or metadata unavailable)."
fi

pr_body_file="$(mktemp)"
{
echo "This PR was auto-generated via a workflow action."
echo
echo "## Included Pull Requests"
echo "${prs_markdown}"
echo
echo "## Diff"
echo "- Source: \`${SOURCE_BRANCH}\`"
echo "- Target: \`${DESTINATION_BRANCH}\`"
echo "- Commits ahead: ${ahead_by}"
echo "- Compare: ${compare_url}"
} > "${pr_body_file}"

pr_number="$(gh api "repos/${REPO}/pulls" \
-f state="open" \
-f base="${DESTINATION_BRANCH}" \
-f head="${OWNER}:${SOURCE_BRANCH}" \
--jq '.[0].number // empty')"

if [ -z "${pr_number}" ]; then
echo "No open PR found for ${SOURCE_BRANCH} -> ${DESTINATION_BRANCH}. Creating one."
create_payload="$(jq -n \
--arg title "${PR_TITLE}" \
--arg head "${SOURCE_BRANCH}" \
--arg base "${DESTINATION_BRANCH}" \
--rawfile body "${pr_body_file}" \
'{title: $title, head: $head, base: $base, body: $body}')"

pr_number="$(gh api \
-X POST "repos/${REPO}/pulls" \
--input - \
--jq '.number' <<<"${create_payload}")"
else
echo "Updating existing PR #${pr_number}."
update_payload="$(jq -n \
--arg title "${PR_TITLE}" \
--rawfile body "${pr_body_file}" \
'{title: $title, body: $body}')"

gh api \
-X PATCH "repos/${REPO}/pulls/${pr_number}" \
--input - <<<"${update_payload}" >/dev/null
fi

gh api \
-X POST "repos/${REPO}/pulls/${pr_number}/requested_reviewers" \
-f reviewers[]="${REVIEWER}" >/dev/null || \
echo "Reviewer assignment skipped for ${REVIEWER}."
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const prettierConfig = require("eslint-config-prettier/flat");

const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
});

module.exports = [
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:coverage": "yarn test --coverage",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint:css": "stylelint './**/*.{js,jsx,ts,tsx}'",
"lint:css": "stylelint './**/*.styles.ts'",
"format": "prettier . --write",
"format:check": "prettier . --check",
"prepare": "husky",
Expand Down Expand Up @@ -76,6 +76,7 @@
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.1",
"lint-staged": "^16.2.4",
"postcss-styled-syntax": "^0.7.1",
"prettier": "^3.8.1",
"react-test-renderer": "^18.0.0",
"redis-mock": "^0.47.0",
Expand Down
1 change: 1 addition & 0 deletions stylelint.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
module.exports = {
extends: ["stylelint-config-recommended"],
customSyntax: "postcss-styled-syntax",
};
12 changes: 12 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3431,6 +3431,7 @@ __metadata:
next: "npm:^14.2.0"
next-redux-wrapper: "npm:^8.1.0"
nprogress: "npm:^0.2.0"
postcss-styled-syntax: "npm:^0.7.1"
prettier: "npm:^3.8.1"
quagga: "npm:^0.12.1"
react: "npm:^18.0.0"
Expand Down Expand Up @@ -8048,6 +8049,17 @@ __metadata:
languageName: node
linkType: hard

"postcss-styled-syntax@npm:^0.7.1":
version: 0.7.1
resolution: "postcss-styled-syntax@npm:0.7.1"
dependencies:
typescript: "npm:^5.7.3"
peerDependencies:
postcss: ^8.5.1
checksum: 10c0/85339ca0c511c88cb46bd3e2cdc1bc7ff695960946b653f411939f06cb47bd3e4f2d47e580cf949e56978153c49b462702c9e71d598f1e38619569783e431073
languageName: node
linkType: hard

"postcss-value-parser@npm:^4.0.2":
version: 4.0.2
resolution: "postcss-value-parser@npm:4.0.2"
Expand Down
Loading