Skip to content
34 changes: 25 additions & 9 deletions .github/workflows/deployment-v2.yml

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: Deployment v2

on:
push:
branches: [ main ]
tags: [ cowswap-*, explorer-* ]
branches: [main]
tags: [cowswap-*, explorer-*]

concurrency:
group: ${{ startsWith(github.ref, 'refs/tags/') && format('release-tag-{0}', github.sha) || 'release-branch-sync' }}
Expand All @@ -19,11 +19,13 @@ jobs:
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
outputs:
release-commit: ${{ steps.collect.outputs.release-commit }}
release-tags: ${{ steps.collect.outputs.release-tags }}
steps:
- name: Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: refs/heads/main
fetch-depth: 0
persist-credentials: false

Expand All @@ -32,9 +34,15 @@ jobs:
run: |
set -euo pipefail

git fetch --tags origin
git fetch --tags origin main

release_commit="$(git rev-list -n 1 "${GITHUB_REF}")"

if ! git merge-base --is-ancestor "${release_commit}" "origin/main"; then
echo "::error::Release tag ${GITHUB_REF_NAME} does not point to a commit reachable from origin/main"
exit 1
fi

release_tags="$(
git tag --points-at "${release_commit}" \
| sort \
Expand All @@ -45,6 +53,7 @@ jobs:
release_tags="${GITHUB_REF_NAME}"
fi

echo "release-commit=${release_commit}" >> "$GITHUB_OUTPUT"
echo "release-tags=${release_tags}" >> "$GITHUB_OUTPUT"

sync-develop:
Expand All @@ -61,6 +70,7 @@ jobs:
- name: Checkout workflow repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: refs/heads/main
fetch-depth: 0
persist-credentials: false

Expand Down Expand Up @@ -132,6 +142,7 @@ jobs:
- name: Checkout workflow repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: refs/heads/main
fetch-depth: 0
persist-credentials: false

Expand All @@ -148,15 +159,17 @@ jobs:
run: |
set -euo pipefail

git fetch origin main staging
git fetch origin main staging --tags
git checkout -B staging origin/staging
git merge --ff-only origin/main
git merge --ff-only "${RELEASE_COMMIT}"
git push origin staging
env:
RELEASE_COMMIT: ${{ needs.collect-release-metadata.outputs.release-commit }}

notify-production-approval:
name: Notify Slack for production approval
if: startsWith(github.ref, 'refs/tags/cowswap-') || startsWith(github.ref, 'refs/tags/explorer-')
needs: [ collect-release-metadata, sync-staging ]
needs: [collect-release-metadata, sync-staging]
runs-on: ubuntu-latest
steps:
- name: Notify Slack
Expand All @@ -174,13 +187,14 @@ jobs:
sync-production:
name: Fast-forward production to main
if: startsWith(github.ref, 'refs/tags/cowswap-') || startsWith(github.ref, 'refs/tags/explorer-')
needs: [ collect-release-metadata, notify-production-approval ]
needs: [collect-release-metadata, notify-production-approval]
runs-on: ubuntu-latest
environment: production # Env configured in GitHub UI. Requires manual approval before this job can run
steps:
- name: Checkout workflow repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: refs/heads/main
fetch-depth: 0
persist-credentials: false
- name: Setup release sync
Expand All @@ -196,7 +210,9 @@ jobs:
run: |
set -euo pipefail

git fetch origin main production
git fetch origin main production --tags
git checkout -B production origin/production
git merge --ff-only origin/main
git merge --ff-only "${RELEASE_COMMIT}"
git push origin production
env:
RELEASE_COMMIT: ${{ needs.collect-release-metadata.outputs.release-commit }}
80 changes: 73 additions & 7 deletions .github/workflows/deployment.yml

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As Sasha mentioned, this one can remain untouched as it'll be removed soon.

Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: Deployment
on:
# build when pushing to main/develop, or create a release
push:
branches: [ main, develop ]
tags: [ cowswap-v*, explorer-v* ]
branches: [main, develop]
tags: [cowswap-v*, explorer-v*]
workflow_dispatch: # Manually trigger it via UI/CLI/API
inputs:
app:
Expand All @@ -16,7 +16,39 @@ on:
- EXPLORER
- ALL

permissions:
contents: read

jobs:
validate-release-tag:
name: Validate release tag
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
outputs:
release-commit: ${{ steps.validate.outputs.release-commit }}
steps:
- name: Checkout trusted workflow repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: refs/heads/main
fetch-depth: 0
persist-credentials: false

- name: Validate release commit
id: validate
run: |
set -euo pipefail

git fetch origin main --tags

release_commit="$(git rev-list -n 1 "${GITHUB_REF}")"

if ! git merge-base --is-ancestor "${release_commit}" "origin/main"; then
echo "::error::Release tag ${GITHUB_REF_NAME} does not point to a commit reachable from origin/main"
exit 1
fi

echo "release-commit=${release_commit}" >> "$GITHUB_OUTPUT"

vercel-dev:
# Deploys to Vercel dev environment
Expand All @@ -26,7 +58,7 @@ jobs:
secrets: inherit
strategy:
matrix:
app: [ EXPLORER, COWSWAP ]
app: [EXPLORER, COWSWAP]
with:
env_name: dev
app: ${{ matrix.app }}
Expand All @@ -35,15 +67,49 @@ jobs:
# Deploys to Vercel staging environment only when there is a tag for CowSwap or Explorer
name: Vercel pre-prod
if: startsWith(github.ref, 'refs/tags')
uses: ./.github/workflows/vercel.yml
secrets: inherit
needs: validate-release-tag

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, we should remove deployment.yml soon due to the new deployment flow. @alfetopito Am I right? If yes, probably it's better to not tuch this file at all in order to reduce the PR changes scope

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes!
It's in my todo list after we move prod over to cf-pages.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok reverted the file now ec41df5

uses: cowprotocol/cowswap/.github/workflows/vercel.yml@main
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
secrets:
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
VERCEL_PROJECT_ID_COWSWAP: ${{ secrets.VERCEL_PROJECT_ID_COWSWAP }}
VERCEL_PROJECT_ID_EXPLORER: ${{ secrets.VERCEL_PROJECT_ID_EXPLORER }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
REACT_APP_PINATA_API_KEY: ${{ secrets.REACT_APP_PINATA_API_KEY }}
REACT_APP_PINATA_SECRET_API_KEY: ${{ secrets.REACT_APP_PINATA_SECRET_API_KEY }}
REACT_APP_BLOCKNATIVE_API_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_API_KEY }}
REACT_APP_GOOGLE_ANALYTICS_ID: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID }}
REACT_APP_LAUNCH_DARKLY_KEY: ${{ secrets.REACT_APP_LAUNCH_DARKLY_KEY }}
REACT_APP_INFURA_KEY: ${{ secrets.REACT_APP_INFURA_KEY }}
REACT_APP_NETWORK_URL_1: ${{ secrets.REACT_APP_NETWORK_URL_1 }}
REACT_APP_NETWORK_URL_56: ${{ secrets.REACT_APP_NETWORK_URL_56 }}
REACT_APP_NETWORK_URL_100: ${{ secrets.REACT_APP_NETWORK_URL_100 }}
REACT_APP_NETWORK_URL_137: ${{ secrets.REACT_APP_NETWORK_URL_137 }}
REACT_APP_NETWORK_URL_8453: ${{ secrets.REACT_APP_NETWORK_URL_8453 }}
REACT_APP_NETWORK_URL_9745: ${{ secrets.REACT_APP_NETWORK_URL_9745 }}
REACT_APP_NETWORK_URL_42161: ${{ secrets.REACT_APP_NETWORK_URL_42161 }}
REACT_APP_NETWORK_URL_43114: ${{ secrets.REACT_APP_NETWORK_URL_43114 }}
REACT_APP_NETWORK_URL_57073: ${{ secrets.REACT_APP_NETWORK_URL_57073 }}
REACT_APP_NETWORK_URL_59144: ${{ secrets.REACT_APP_NETWORK_URL_59144 }}
REACT_APP_NETWORK_URL_11155111: ${{ secrets.REACT_APP_NETWORK_URL_11155111 }}
REACT_APP_WC_PROJECT_ID: ${{ secrets.REACT_APP_WC_PROJECT_ID }}
REACT_APP_IPFS_READ_URI: ${{ secrets.REACT_APP_IPFS_READ_URI }}
EXPLORER_SENTRY_DSN: ${{ secrets.EXPLORER_SENTRY_DSN }}
REACT_APP_SUBGRAPH_URL_MAINNET: ${{ secrets.REACT_APP_SUBGRAPH_URL_MAINNET }}
REACT_APP_SUBGRAPH_URL_ARBITRUM_ONE: ${{ secrets.REACT_APP_SUBGRAPH_URL_ARBITRUM_ONE }}
REACT_APP_SUBGRAPH_URL_BASE: ${{ secrets.REACT_APP_SUBGRAPH_URL_BASE }}
REACT_APP_SUBGRAPH_URL_GNOSIS_CHAIN: ${{ secrets.REACT_APP_SUBGRAPH_URL_GNOSIS_CHAIN }}
BFF_BASE_URL: ${{ secrets.BFF_BASE_URL }}
CMS_BASE_URL: ${{ secrets.CMS_BASE_URL }}
REACT_APP_NEAR_API_KEY: ${{ secrets.REACT_APP_NEAR_API_KEY }}
strategy:
matrix:
env_name: [ staging ] # deploys both in parallel
env_name: [staging] # deploys both in parallel
with:
env_name: ${{ matrix.env_name }}
# Pick app according to published tag
app: ${{ startsWith(github.ref, 'refs/tags/explorer') && 'EXPLORER' || 'COWSWAP' }}
checkout_ref: ${{ needs.validate-release-tag.outputs.release-commit }}
disable_nx_cache: true

vercel-prod:
Expand All @@ -62,7 +128,7 @@ jobs:

notify-failure:
name: Notify Slack on Failure
needs: [ vercel-dev, vercel-pre-prod, vercel-prod ]
needs: [vercel-dev, vercel-pre-prod, vercel-prod]
runs-on: ubuntu-latest
if: failure() && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop')

Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/vercel.yml

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ on:
description: 'Application to deploy. Options are: COWSWAP, EXPLORER'
required: true
type: string
checkout_ref:
description: 'Exact git ref or commit to check out before building'
required: false
type: string
default: ''
disable_nx_cache:
description: 'Disable NX cache'
required: false
Expand All @@ -34,6 +39,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
ref: ${{ inputs.checkout_ref != '' && inputs.checkout_ref || github.sha }}

- name: Install pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { CowSwapWidgetParams, TradeType } from '@cowprotocol/widget-lib'

import { vanillaNoDepsExample } from './htmlExample'
import { jsExample } from './jsExample'
import { tsExample } from './tsExample'

import { ColorPalette } from '../../configurator/types'

const defaultPalette: ColorPalette = {
primary: '#000000',
background: '#111111',
paper: '#222222',
text: '#ffffff',
}

describe('widget snippet serialization', () => {
it('escapes script-breaking token values in the HTML snippet', () => {
const params: CowSwapWidgetParams = {
appCode: 'Widget App',
sell: {
asset: '</script><script>alert(1)</script>',
},
}

const snippet = vanillaNoDepsExample(params, defaultPalette)

expect(snippet).not.toContain('</script><script>alert(1)</script>')
expect(snippet).toContain('\\u003c/script\\u003e\\u003cscript\\u003ealert(1)\\u003c/script\\u003e')
})

it('drops invalid tradeType values from Javascript snippets', () => {
const params = {
appCode: 'Widget App',
tradeType: 'swap";alert(1);//',
} as unknown as CowSwapWidgetParams

const snippet = jsExample(params, defaultPalette)

expect(snippet).not.toContain('tradeType')
expect(snippet).not.toContain('alert(1)')
})

it('emits TradeType enums only for valid Typescript trade types', () => {
const validParams: CowSwapWidgetParams = {
appCode: 'Widget App',
tradeType: TradeType.ADVANCED,
enabledTradeTypes: [TradeType.SWAP, TradeType.YIELD],
}

const validSnippet = tsExample(validParams, defaultPalette)

expect(validSnippet).toContain('TradeType.ADVANCED')
expect(validSnippet).toContain('TradeType.SWAP')
expect(validSnippet).toContain('TradeType.YIELD')

const invalidParams = {
appCode: 'Widget App',
tradeType: 'advanced};alert(1);//',
enabledTradeTypes: [TradeType.SWAP, 'yield);alert(1);//'],
} as unknown as CowSwapWidgetParams

const invalidSnippet = tsExample(invalidParams, defaultPalette)

expect(invalidSnippet).not.toContain('alert(1)')
expect(invalidSnippet).not.toContain('TradeType.ADVANCED};ALERT(1);//')
expect(invalidSnippet).toContain('TradeType.SWAP')
})

it('handles malformed trade type shapes safely', () => {
const malformedParams = {
appCode: 'Widget App',
tradeType: '',
enabledTradeTypes: 'swap',
} as unknown as CowSwapWidgetParams

expect(() => jsExample(malformedParams, defaultPalette)).not.toThrow()
expect(() => tsExample(malformedParams, defaultPalette)).not.toThrow()

const jsSnippet = jsExample(malformedParams, defaultPalette)
const tsSnippet = tsExample(malformedParams, defaultPalette)

expect(jsSnippet).not.toContain('tradeType')
expect(jsSnippet).not.toContain('enabledTradeTypes')
expect(tsSnippet).not.toContain('tradeType')
expect(tsSnippet).not.toContain('enabledTradeTypes')
})
})
Loading
Loading