Skip to content

Commit 1399d60

Browse files
committed
Merge branch 'develop' into main-copy
2 parents d4c8430 + 79e9e46 commit 1399d60

22 files changed

Lines changed: 1827 additions & 1417 deletions

File tree

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
name: Setup Release Sync
2+
description: Create a GitHub App token, resolve the app bot identity, and checkout the repository
3+
4+
inputs:
5+
app-id:
6+
description: GitHub App ID
7+
required: true
8+
private-key:
9+
description: GitHub App private key
10+
required: true
11+
owner:
12+
description: Repository owner
13+
required: true
14+
repository:
15+
description: Repository name
16+
required: true
17+
checkout-ref:
18+
description: Optional git ref to checkout
19+
required: false
20+
default: ''
21+
pull-requests-write:
22+
description: Whether the app token should include pull request write permission
23+
required: false
24+
default: 'false'
25+
26+
outputs:
27+
token:
28+
description: GitHub App installation token
29+
value: ${{ steps.app-token.outputs.token }}
30+
app-slug:
31+
description: GitHub App slug
32+
value: ${{ steps.app-token.outputs.app-slug }}
33+
app-user-id:
34+
description: Numeric GitHub App bot user id
35+
value: ${{ steps.app-user.outputs.user-id }}
36+
37+
runs:
38+
using: composite
39+
steps:
40+
- name: Create GitHub App token
41+
id: app-token
42+
uses: actions/create-github-app-token@f8d387b68d61c58ab83c6c016672934102569859 # v3.0.0
43+
with:
44+
app-id: ${{ inputs.app-id }}
45+
private-key: ${{ inputs.private-key }}
46+
owner: ${{ inputs.owner }}
47+
repositories: ${{ inputs.repository }}
48+
permission-contents: write
49+
permission-pull-requests: ${{ inputs.pull-requests-write == 'true' && 'write' || '' }}
50+
51+
- name: Get GitHub App user ID
52+
id: app-user
53+
shell: bash
54+
run: echo "user-id=$(gh api "/users/${APP_SLUG}[bot]" --jq .id)" >> "$GITHUB_OUTPUT"
55+
env:
56+
APP_SLUG: ${{ steps.app-token.outputs.app-slug }}
57+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
58+
59+
- name: Checkout code
60+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
61+
with:
62+
fetch-depth: 0
63+
persist-credentials: true
64+
token: ${{ steps.app-token.outputs.token }}
65+
ref: ${{ inputs.checkout-ref != '' && inputs.checkout-ref || github.ref }}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
name: Deployment v2
2+
3+
on:
4+
push:
5+
branches: [main-copy]
6+
tags: [cowswap-*, explorer-*]
7+
8+
concurrency:
9+
group: release-branch-sync
10+
cancel-in-progress: false
11+
12+
permissions:
13+
contents: write
14+
pull-requests: write
15+
16+
jobs:
17+
collect-release-metadata:
18+
name: Collect release metadata
19+
if: startsWith(github.ref, 'refs/tags/')
20+
runs-on: ubuntu-latest
21+
outputs:
22+
release-tags: ${{ steps.collect.outputs.release-tags }}
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
26+
with:
27+
fetch-depth: 0
28+
persist-credentials: false
29+
30+
- name: Collect tags for release commit
31+
id: collect
32+
run: |
33+
set -euo pipefail
34+
35+
git fetch --tags origin
36+
37+
release_commit="$(git rev-list -n 1 "${GITHUB_REF}")"
38+
release_tags="$(
39+
git tag --points-at "${release_commit}" \
40+
| sort \
41+
| paste -sd ', ' -
42+
)"
43+
44+
if [ -z "${release_tags}" ]; then
45+
release_tags="${GITHUB_REF_NAME}"
46+
fi
47+
48+
echo "release-tags=${release_tags}" >> "$GITHUB_OUTPUT"
49+
50+
sync-develop:
51+
name: Sync main-copy to develop
52+
if: github.ref == 'refs/heads/main-copy'
53+
runs-on: ubuntu-latest
54+
env:
55+
TARGET_BRANCH: develop
56+
SYNC_BRANCH: automation/sync-main-copy-to-develop
57+
PR_TITLE: 'chore(sync): merge main-copy into develop'
58+
PR_BODY: |
59+
This PR contains an automated merge commit from `main-copy` into `develop`.
60+
61+
Requested reviewers:
62+
- @cowprotocol/frontend
63+
steps:
64+
- name: Setup release sync
65+
id: setup
66+
uses: ./.github/actions/setup-release-sync
67+
with:
68+
app-id: ${{ vars.COWSWAP_RELEASE_SYNC_APP_ID }}
69+
private-key: ${{ secrets.COWSWAP_RELEASE_SYNC_APP_PRIVATE_KEY }}
70+
owner: ${{ github.repository_owner }}
71+
repository: ${{ github.event.repository.name }}
72+
pull-requests-write: 'true'
73+
74+
- name: Prepare merge branch
75+
id: prepare
76+
run: |
77+
set -euo pipefail
78+
79+
git config user.name "${APP_SLUG}[bot]"
80+
git config user.email "${APP_USER_ID}+${APP_SLUG}[bot]@users.noreply.github.com"
81+
82+
git fetch origin main-copy "${TARGET_BRANCH}"
83+
git checkout -B "${SYNC_BRANCH}" "origin/${TARGET_BRANCH}"
84+
85+
before_sha="$(git rev-parse HEAD)"
86+
git merge --no-ff --no-edit -m "${PR_TITLE}" origin/main-copy
87+
after_sha="$(git rev-parse HEAD)"
88+
89+
if [ "${before_sha}" = "${after_sha}" ]; then
90+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
91+
exit 0
92+
fi
93+
94+
echo "has_changes=true" >> "$GITHUB_OUTPUT"
95+
env:
96+
APP_SLUG: ${{ steps.setup.outputs.app-slug }}
97+
APP_USER_ID: ${{ steps.setup.outputs.app-user-id }}
98+
99+
- name: Create or update pull request
100+
if: steps.prepare.outputs.has_changes == 'true'
101+
id: create-pr
102+
uses: peter-evans/create-pull-request@v8
103+
with:
104+
token: ${{ steps.setup.outputs.token }}
105+
branch: ${{ env.SYNC_BRANCH }}
106+
base: ${{ env.TARGET_BRANCH }}
107+
title: ${{ env.PR_TITLE }}
108+
body: ${{ env.PR_BODY }}
109+
commit-message: ${{ env.PR_TITLE }}
110+
delete-branch: false
111+
draft: false
112+
reviewers: ''
113+
team-reviewers: |
114+
frontend
115+
qa
116+
117+
- name: Notify Slack for develop review
118+
if: steps.prepare.outputs.has_changes == 'true'
119+
run: |
120+
curl -X POST -H "Content-type: application/json" \
121+
--data "{\"text\": \"➡️ Develop sync PR is ready for review. <$PR_URL|Open pull request>.\"}" \
122+
"$SLACK_WEBHOOK_URL"
123+
env:
124+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
125+
PR_URL: ${{ steps.create-pr.outputs.pull-request-url }}
126+
127+
sync-staging:
128+
name: Fast-forward staging to main-copy
129+
if: startsWith(github.ref, 'refs/tags/cowswap-') || startsWith(github.ref, 'refs/tags/explorer-')
130+
needs: collect-release-metadata
131+
runs-on: ubuntu-latest
132+
steps:
133+
- name: Setup release sync
134+
id: setup
135+
uses: ./.github/actions/setup-release-sync
136+
with:
137+
app-id: ${{ vars.COWSWAP_RELEASE_SYNC_APP_ID }}
138+
private-key: ${{ secrets.COWSWAP_RELEASE_SYNC_APP_PRIVATE_KEY }}
139+
owner: ${{ github.repository_owner }}
140+
repository: ${{ github.event.repository.name }}
141+
142+
- name: Fast-forward staging
143+
run: |
144+
set -euo pipefail
145+
146+
git fetch origin main-copy staging
147+
git checkout -B staging origin/staging
148+
git merge --ff-only origin/main-copy
149+
git push origin staging
150+
151+
notify-production-approval:
152+
name: Notify Slack for production approval
153+
if: startsWith(github.ref, 'refs/tags/cowswap-') || startsWith(github.ref, 'refs/tags/explorer-')
154+
needs: [collect-release-metadata, sync-staging]
155+
runs-on: ubuntu-latest
156+
steps:
157+
- name: Notify Slack
158+
run: |
159+
curl -X POST -H "Content-type: application/json" \
160+
--data "{\"text\": \"⏳ Production release for tag(s) \`${RELEASE_TAGS}\` is waiting for approval. <$SERVER_URL/$REPOSITORY/actions/runs/$RUN_ID|Review the workflow run>.\"}" \
161+
"$SLACK_WEBHOOK_URL"
162+
env:
163+
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
164+
RELEASE_TAGS: ${{ needs.collect-release-metadata.outputs.release-tags }}
165+
SERVER_URL: ${{ github.server_url }}
166+
REPOSITORY: ${{ github.repository }}
167+
RUN_ID: ${{ github.run_id }}
168+
169+
sync-production:
170+
name: Fast-forward production to main-copy
171+
if: startsWith(github.ref, 'refs/tags/cowswap-') || startsWith(github.ref, 'refs/tags/explorer-')
172+
needs: [collect-release-metadata, notify-production-approval]
173+
runs-on: ubuntu-latest
174+
environment: production # Env configured in GitHub UI. Requires manual approval before this job can run
175+
steps:
176+
- name: Setup release sync
177+
id: setup
178+
uses: ./.github/actions/setup-release-sync
179+
with:
180+
app-id: ${{ vars.COWSWAP_RELEASE_SYNC_APP_ID }}
181+
private-key: ${{ secrets.COWSWAP_RELEASE_SYNC_APP_PRIVATE_KEY }}
182+
owner: ${{ github.repository_owner }}
183+
repository: ${{ github.event.repository.name }}
184+
185+
- name: Fast-forward production
186+
run: |
187+
set -euo pipefail
188+
189+
git fetch origin main-copy production
190+
git checkout -B production origin/production
191+
git merge --ff-only origin/main-copy
192+
git push origin production

.github/workflows/i18n-extract.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: i18n Extract
2+
3+
on:
4+
pull_request:
5+
types: [ opened, synchronize ]
6+
7+
concurrency:
8+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
9+
cancel-in-progress: true
10+
11+
permissions:
12+
contents: write
13+
14+
env:
15+
NODE_VERSION: lts/jod
16+
17+
jobs:
18+
i18n-extract:
19+
name: Extract i18n strings
20+
runs-on: ubuntu-latest
21+
# Only run for PRs from the same repo (GITHUB_TOKEN can't push to forks)
22+
if: github.event.pull_request.head.repo.full_name == github.repository
23+
24+
steps:
25+
- name: Checkout PR branch
26+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
27+
with:
28+
ref: ${{ github.head_ref }}
29+
persist-credentials: true
30+
31+
- name: Install pnpm
32+
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061 # v4.2.0
33+
34+
- name: Set up node
35+
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
36+
with:
37+
node-version: ${{ env.NODE_VERSION }}
38+
cache: pnpm
39+
40+
- name: Install dependencies
41+
run: pnpm run install:ci --frozen-lockfile
42+
43+
- name: Extract i18n strings
44+
run: pnpm run i18n:extract
45+
46+
- name: Commit and push if changed
47+
run: |
48+
if git diff --quiet 'apps/cowswap-frontend/src/locales/*.po'; then
49+
echo "No i18n changes detected in changed files"
50+
else
51+
git config user.name "github-actions[bot]"
52+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
53+
git add 'apps/cowswap-frontend/src/locales/*.po'
54+
git commit -m "chore(i18n): extract i18n strings [automatic]"
55+
git push
56+
fi

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ providing MEV protection.
1414
| CoW Protocol | [cow.fi](https://cow.fi) |
1515
| Docs | [docs.cow.fi](https://docs.cow.fi) |
1616
| Governance (Snapshot) | [snapshot.org/#/cow.eth](https://snapshot.org/#/cow.eth) |
17-
| Stats | [dune.com/cowprotocol/cowswap](https://dune.com/cowprotocol/cowswap) |
17+
| Stats | [dune.com/cowprotocol/cowswap](https://dune.com/cowprotocol/cow-swap-home) |
1818
| X/Twitter | [@CoWSwap](https://twitter.com/CoWSwap) |
1919
| Discord | [discord.com/invite/cowprotocol](https://discord.com/invite/cowprotocol) |
2020
| Forum | [forum.cow.fi](https://forum.cow.fi) |

apps/cow-fi/app/(main)/affiliate-program/page.tsx

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ import IMG_ICON_COW_LENS from '@cowprotocol/assets/images/icon-cow-lens.svg'
66
import IMG_ICON_FAQ from '@cowprotocol/assets/images/icon-faq.svg'
77
import IMG_COWSWAP_HERO from '@cowprotocol/assets/images/image-affiliate-hero.svg'
88
import { useFeatureFlags } from '@cowprotocol/common-hooks'
9-
import { ProductLogo, ProductVariant, UI } from '@cowprotocol/ui'
9+
import { Media, ProductLogo, ProductVariant, UI } from '@cowprotocol/ui'
1010

1111
import { CowFiCategory } from 'src/common/analytics/types'
12+
import styled from 'styled-components/macro'
1213

1314
import FAQ from '@/components/FAQ'
1415
import LazySVG from '@/components/LazySVG'
@@ -43,6 +44,23 @@ import {
4344
TopicTitle,
4445
} from '@/styles/styled'
4546

47+
const FooterCtaLinkOuter = styled.div`
48+
${Media.upToExtraSmall()} {
49+
width: 100%;
50+
box-sizing: border-box;
51+
align-self: stretch;
52+
margin: 0;
53+
54+
a {
55+
display: block;
56+
width: 100%;
57+
box-sizing: border-box;
58+
line-height: 1.35;
59+
padding: 14px 16px;
60+
}
61+
}
62+
`
63+
4664
type SendEvent = (action: string) => void
4765
function AffiliateHero({ sendEvent }: { sendEvent: SendEvent }): ReactNode {
4866
return (
@@ -217,17 +235,19 @@ function FooterCtaSection({ sendEvent }: { sendEvent: SendEvent }): ReactNode {
217235
<SectionTitleDescription fontSize={28} color={`var(${UI.COLOR_NEUTRAL_30})`}>
218236
Generate your link. Share it. Earn USDC - every week.
219237
</SectionTitleDescription>
220-
<Link
221-
bgColor={`var(${UI.COLOR_YELLOW_300_PRIMARY})`}
222-
color={`var(${UI.COLOR_YELLOW_800_PRIMARY})`}
223-
href={AFFILIATE_PROGRAM_CTA.href}
224-
external
225-
linkType={LinkType.SectionTitleButton}
226-
utmContent="affiliate-program-footer-generate-link"
227-
onClick={() => sendEvent('click-generate-referral-link')}
228-
>
229-
Generate your referral link &#8594;
230-
</Link>
238+
<FooterCtaLinkOuter>
239+
<Link
240+
bgColor={`var(${UI.COLOR_YELLOW_300_PRIMARY})`}
241+
color={`var(${UI.COLOR_YELLOW_800_PRIMARY})`}
242+
href={AFFILIATE_PROGRAM_CTA.href}
243+
external
244+
linkType={LinkType.SectionTitleButton}
245+
utmContent="affiliate-program-footer-generate-link"
246+
onClick={() => sendEvent('click-generate-referral-link')}
247+
>
248+
Generate your referral link &#8594;
249+
</Link>
250+
</FooterCtaLinkOuter>
231251
</SectionTitleWrapper>
232252
</ContainerCardSection>
233253
</ContainerCard>

0 commit comments

Comments
 (0)