Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ci: automated manuals #1216

Merged
merged 8 commits into from
Jan 7, 2025
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
161 changes: 158 additions & 3 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
name: frontend e2e tests
name: cypress

on:
pull_request:
branches: [ main ]
paths: [ "apps/admin-panel/**" ]
push:
branches: [ main ]
paths: [ "apps/admin-panel/**" ]
workflow_dispatch:

jobs:
tilt-ci:
name: manual generation / execute via tilt and cypress
cypress-test-run-in-browserstack:
name: browserstack / local tunnel into tilt up
runs-on: ubuntu-latest
steps:
- uses: docker/login-action@v3
Expand Down Expand Up @@ -50,3 +56,152 @@ jobs:
env:
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}

- name: upload cypress screenshots
uses: actions/upload-artifact@v4
with:
name: screenshots
path: apps/admin-panel/cypress/manuals/screenshots/*

manual-generation:
name: manual pdfs / upload to lana-manuals
needs: cypress-test-run-in-browserstack
runs-on: ubuntu-latest
steps:
- uses: DeterminateSystems/nix-installer-action@v4
- uses: DeterminateSystems/magic-nix-cache-action@v8
- uses: actions/checkout@v4
- run: mkdir -p apps/admin-panel/cypress/manuals/screenshots
- uses: actions/download-artifact@v4
with:
name: screenshots
path: apps/admin-panel/cypress/manuals/screenshots
- name: generate pdfs
run: cd apps/admin-panel && nix develop -c pnpm run local:pdf
- run: ls -R apps/admin-panel/cypress/manuals
- uses: actions/upload-artifact@v4
with:
name: pdfs
path: apps/admin-panel/cypress/manuals/results/*
- name: generate manual page
run: |
cd apps/admin-panel/cypress/manuals/results
cat <<EOF > index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lana Bank Manuals</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 font-sans">
<div class="max-w-5xl mx-auto mt-10 p-5">
<h1 class="text-3xl font-bold text-center text-gray-800 mb-6">
Lana Bank - Manuals for Regulators
</h1>
<div class="overflow-x-auto">
<table class="w-full border-collapse bg-white shadow-md rounded-lg">
<thead>
<tr class="bg-gray-800 text-white">
<th class="py-3 px-5 text-left">#</th>
<th class="py-3 px-5 text-left">Manual Name</th>
<th class="py-3 px-5 text-left">View</th>
</tr>
</thead>
<tbody>
EOF

COUNTER=1
for pdf in *.pdf; do
echo "<tr class='hover:bg-gray-50 border-b'>
<td class='py-3 px-5'>$COUNTER</td>
<td class='py-3 px-5'>${pdf%.pdf}</td>
<td class='py-3 px-5'>
<a href='$pdf' class='text-blue-600 hover:underline' target='_blank'>Open</a>
</td>
</tr>" >> index.html
((COUNTER++))
done

cat <<EOF >> index.html
</tbody>
</table>
</div>
</div>
</body>
</html>
EOF

- name: Deploy to Netlify (Pull Request)
id: netlify_deploy
if: github.event_name == 'pull_request'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: 61296920-bd52-43a3-9253-78db17a78d9c
run: |
GITHUB_SHA="${{ github.sha }}"
SHORT_SHA="${GITHUB_SHA::7}"
ALIAS="pr-${{ github.event.pull_request.number }}-commit-${SHORT_SHA}"
netlify deploy \
--dir=apps/admin-panel/cypress/manuals/results \
--site=$NETLIFY_SITE_ID \
--auth=$NETLIFY_AUTH_TOKEN \
--alias="$ALIAS" \
--message="Manuals Preview for PR #${{ github.event.pull_request.number }} Commit $GITHUB_SHA" \
--json > deploy-info.json
DEPLOY_URL=$(jq -r '.deploy_url' deploy-info.json)
echo "deploy_url=$DEPLOY_URL" >> $GITHUB_OUTPUT

- name: Deploy to Netlify (Push to Main)
if: github.event_name == 'push'
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: 61296920-bd52-43a3-9253-78db17a78d9c
run: |
netlify deploy \
--prod \
--dir=apps/admin-panel/cypress/manuals/results \
--site=$NETLIFY_SITE_ID \
--auth=$NETLIFY_AUTH_TOKEN \
--message="Manuals Build for Commit ${{ github.sha }}" \
--json > deploy-info.json
DEPLOY_URL=$(jq -r '.deploy_url' deploy-info.json)
echo "deploy_url=$DEPLOY_URL" >> $GITHUB_OUTPUT

- name: Create or Update Preview Comment
if: github.event_name == 'pull_request'
uses: actions/github-script@v6
with:
script: |
const prNumber = context.payload.pull_request.number;
const deployUrl = '${{ steps.netlify_deploy.outputs.deploy_url }}';
const commentBody = `<!-- Manuals Preview Comment -->\nManuals preview: [Link to Manuals](${deployUrl})`;
// Fetch existing comments on the PR
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
// Identify if the bot has already made a comment
const botLogin = 'github-actions[bot]'
const existingComment = comments.find(
comment => comment.user.login === botLogin && comment.body.includes('<!-- Manuals Preview Comment -->')
);
if (existingComment) {
// Update the existing comment
await github.rest.issues.updateComment({
owner: context.repo.owner,
repo: context.repo.repo,
comment_id: existingComment.id,
body: commentBody,
});
} else {
// Create a new comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: commentBody,
});
}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ tilt-in-ci:
./dev/bin/tilt-ci.sh

test-cypress-in-ci-through-browserstack:
cd apps/admin-panel && pnpm run cypress:run:browserstack
cd apps/admin-panel && pnpm cypress:run browserstack

push-dataform-branch:
git push -f origin HEAD:${DATAFORM_BRANCH}
Expand Down
18 changes: 10 additions & 8 deletions apps/admin-panel/browserstack.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,9 @@
},
"browsers": [
{
"browser": "chrome",
"os": "Windows 11",
"versions": [
"latest"
]
"browser": "chrome",
"versions": ["latest"]
}
],
"run_settings": {
Expand All @@ -20,22 +18,26 @@
"npm_dependencies": {
"typescript": "^4",
"browserstack-cypress-cli": "latest",
"cypress": "latest"
"cypress": "latest",
"cypress-file-upload": "latest",
"@apollo/client": "latest",
"graphql": "latest",
"react": "18",
"@faker-js/faker": "latest"
},
"exclude": [
"node_modules/**/*",
".git/**/*",
".next/**/*"
],
"headed": true,
"resolution": "2560x1440",
"downloads": [
"./results",
"./cypress/screenshots"
"./cypress"
]
},
"connection_settings": {
"local": false
"local": true
},
"disable_usage_reporting": false
}
11 changes: 8 additions & 3 deletions apps/admin-panel/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { defineConfig } from "cypress"

const multiplier = 100 // Browserstack local tunnel on GHA Runner can be quite slow

export default defineConfig({
e2e: {
specPattern: [
Expand All @@ -17,9 +19,12 @@ export default defineConfig({
"cypress/e2e/profit-and-loss.cy.ts",
],
baseUrl: "http://localhost:4455/admin-panel",
defaultCommandTimeout: 10000,
requestTimeout: 10000,
video: false,
defaultCommandTimeout: 4000 * multiplier,
requestTimeout: 5000 * multiplier,
pageLoadTimeout: 60000 * multiplier,
retries: 5,
screenshotOnRunFailure: false,
video: true,
screenshotsFolder: "cypress/manuals/screenshots",
env: {
MAGIC_LINK: process.env.MAGIC_LINK,
Expand Down
6 changes: 3 additions & 3 deletions apps/admin-panel/cypress/e2e/credit-facilities.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ describe("credit facility", () => {
.type(committeeName)
.should("have.value", committeeName)
cy.get('[data-testid="committee-create-submit-button"]').click()
cy.contains("Committee created successfully").should("be.visible")
cy.url().should("include", "/committees/")
cy.contains(committeeName).should("be.visible")

cy.get('[data-testid="committee-add-member-button"]').click()
cy.get('[data-testid="committee-add-user-select"]').should("be.visible").click()
Expand Down Expand Up @@ -112,7 +113,7 @@ describe("credit facility", () => {
Cypress.env("creditFacilityId", facilityId)
})

cy.contains("Credit Facility created successfully").should("be.visible")
cy.contains("No Collateral").should("be.visible")
cy.takeScreenshot("5_credit_facility_created_success")
})

Expand Down Expand Up @@ -204,7 +205,6 @@ describe("credit facility", () => {
/\/disbursals\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/,
)

cy.contains("Disbursal initiated successfully").should("be.visible")
cy.takeScreenshot("15_disbursal_page")
cy.takeScreenshot("16_disbursal_success_message")

Expand Down
16 changes: 10 additions & 6 deletions apps/admin-panel/cypress/e2e/governance.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,16 @@ describe("Governance Test", () => {
cy.get('[data-testid="committee-create-submit-button"]').click()
cy.takeScreenshot("4_step-submit-committee-creation")

cy.contains("Committee created successfully").should("be.visible")
cy.takeScreenshot("5_step-committee-created-successfully")

cy.getIdFromUrl("/committees/").then((id) => {
committeeId = id
})
cy.url()
.should("include", "/committees/")
.then(() => {
cy.contains(committeeName).should("be.visible")
cy.takeScreenshot("5_step-committee-created-successfully")

cy.getIdFromUrl("/committees/").then((id) => {
committeeId = id
})
})
})

it("should show newly added committee in the list", () => {
Expand Down
9 changes: 6 additions & 3 deletions apps/admin-panel/cypress/e2e/transactions.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,12 @@ describe("Transactions Deposit and Withdraw", () => {

cy.get('[data-testid="withdraw-submit-button"]').click()

cy.contains("Withdrawal initiated successfully").should("be.visible")
cy.contains(`$${withdrawAmount.toLocaleString()}.00`).should("be.visible")
cy.takeScreenshot("11_withdrawal_submit")
cy.url()
.should("include", "/withdrawals/")
.then(() => {
cy.contains(`$${withdrawAmount.toLocaleString()}.00`).should("be.visible")
cy.takeScreenshot("11_withdrawal_submit")
})
})

it("should show newly created Withdraw in list page", () => {
Expand Down
12 changes: 6 additions & 6 deletions apps/admin-panel/cypress/e2e/user.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,17 @@ describe("Users", () => {
cy.get('[data-testid="create-user-submit-button"]').click()
cy.takeScreenshot("5_submit_creation")

cy.contains("Magic link sent successfully").should("be.visible")
cy.takeScreenshot("6_verify_creation")
cy.url()
.should("include", "/users/")
.then((url) => {
userId = url.split("/users/")[1]
cy.takeScreenshot("6_verify_creation")
})

cy.get("[data-testid=user-details-email]")
.should("be.visible")
.invoke("text")
.should("eq", userEmail)

cy.url().then((url) => {
userId = url.split("/users/")[1]
})
})

it("should show newly created user in the list", () => {
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
10 changes: 8 additions & 2 deletions apps/admin-panel/cypress/manuals/local-pdf.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#!/usr/bin/env bash

REPO_ROOT=$(git rev-parse --show-toplevel)
MANUALS_DIR="${REPO_ROOT}/apps/admin-panel/cypress/manuals/results"
mkdir -p "$MANUALS_DIR"

for file in *.md; do
cat > temp.css << 'EOL'
body {
Expand Down Expand Up @@ -86,9 +90,9 @@ EOL

# First, preprocess the markdown to convert special page break markers to HTML
sed 's/<!-- new-page -->/<div class="pb"><\/div>/g' "$file" > "temp.md"

pandoc "temp.md" \
-o "results/${file%.md}.pdf" \
-o "${MANUALS_DIR}/${file%.md}.pdf" \
--pdf-engine=wkhtmltopdf \
--pdf-engine-opt=--enable-local-file-access \
--pdf-engine-opt=--enable-internal-links \
Expand All @@ -101,3 +105,5 @@ EOL
rm temp.md
done
rm temp.css

echo "Manuals generated in ${MANUALS_DIR}"
2 changes: 2 additions & 0 deletions apps/admin-panel/cypress/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,6 @@ elif [[ $EXECUTION_MODE == "headless" ]]; then
nix develop -c pnpm run cypress:run-headless
elif [[ $EXECUTION_MODE == "browserstack" ]]; then
nix develop -c pnpm run cypress:run-browserstack
mv $(find build_artifacts -type d -name "screenshots") cypress/manuals
rm -rf build_artifacts
fi
4 changes: 2 additions & 2 deletions apps/admin-panel/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ beforeEach(() => {
cy.session(
"loginSession",
() => {
cy.visit(Cypress.env("MAGIC_LINK"))
cy.contains("Dashboard", { timeout: 10000 })
cy.visit(Cypress.env("MAGIC_LINK"), { timeout: 60000 })
cy.contains("Dashboard", { timeout: 60000 })
},
{ cacheAcrossSpecs: true },
)
Expand Down
2 changes: 1 addition & 1 deletion apps/admin-panel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"cypress:run": "./cypress/run.sh",
"cypress:run-local": "MAGIC_LINK=$MAGIC_LINK cypress open --env MAGIC_LINK=$MAGIC_LINK",
"cypress:run-headless": "MAGIC_LINK=$MAGIC_LINK cypress run --env MAGIC_LINK=$MAGIC_LINK",
"cypress:open-browserstack": "MAGIC_LINK=$MAGIC_LINK browserstack-cypress run --env MAGIC_LINK=$MAGIC_LINK",
"cypress:run-browserstack": "MAGIC_LINK=$MAGIC_LINK browserstack-cypress run --env MAGIC_LINK=$MAGIC_LINK",
"local:pdf": "cd cypress/manuals && ./local-pdf.sh"
},
"dependencies": {
Expand Down
Loading
Loading