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

update screenshot tests to public s3 #463

Merged
merged 23 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
a3e4626
add tests for graybox-bacom
JackySun9 Oct 1, 2024
595509b
just use chrome
JackySun9 Oct 1, 2024
6428961
add more waiting time
JackySun9 Oct 1, 2024
489f826
add merch card
JackySun9 Oct 2, 2024
5c4f0b2
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 3, 2024
938bdf3
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 8, 2024
59cf385
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 15, 2024
b5d1200
add 404 checker for graxybox-bacom
JackySun9 Oct 15, 2024
5395d47
update gitignore and file name
JackySun9 Oct 15, 2024
6b9c2ca
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 17, 2024
6a3537d
add screenshots for graybox-dc
JackySun9 Oct 17, 2024
113c31a
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 21, 2024
4acbc01
add 404 checking for graybox dc
JackySun9 Oct 21, 2024
2218081
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 22, 2024
0dcda7e
adjust screenshot tests
JackySun9 Oct 23, 2024
6a8dace
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 23, 2024
5122a9b
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Oct 29, 2024
d37fb5f
Merge branch 'main' of https://github.com/adobecom/nala
JackySun9 Nov 13, 2024
c459ae1
update screenshot tests to public s3 and git action to run them
JackySun9 Nov 14, 2024
a04e6e0
fix git action
JackySun9 Nov 14, 2024
f14822f
update git action
JackySun9 Nov 14, 2024
233cbfc
install dependencies
JackySun9 Nov 14, 2024
b83d3cb
only able to run hlx.live pages not stage pages
JackySun9 Nov 14, 2024
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
48 changes: 48 additions & 0 deletions .github/workflows/run-screendiff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Run ScreenDiff Manually

on:
workflow_dispatch:
inputs:
category:
description: 'Test category to run (leave empty to run all, or specify one: milo,feds,caas,uar,uar-ai)'
required: false
type: string

jobs:
test-matrix:
name: Running ${{ inputs.category }} tests
strategy:
fail-fast: false
matrix:
include:
- platform: macos-latest
categories: ["milo","feds","caas","uar","uar-ai"]
runs-on: ${{ matrix.platform }}

steps:
- name: Check out repository
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: lts/*

- name: Run Nala
run: |
if [ -n "${{ inputs.category }}" ]; then
bash runScreenDiff.sh ${{ inputs.category }}
else
for category in ${{ join(matrix.categories, ' ') }}; do
bash runScreenDiff.sh $category
done
fi
shell: bash
env:
IMS_EMAIL: ${{ secrets.IMS_EMAIL }}
IMS_PASS: ${{ secrets.IMS_PASS }}
HLX_TKN: ${{ secrets.HLX_TKN }}
SLACK_WH: ${{ secrets.SLACK_WH }}
AWS_ACCESS_KEY_ID: ${{secrets.AWS_ACCESS_KEY_ID}}
AWS_SECRET_ACCESS_KEY: ${{secrets.AWS_SECRET_ACCESS_KEY}}
AWS_ROLE_ARN: ${{secrets.AWS_ROLE_ARN}}
118 changes: 118 additions & 0 deletions libs/screenshot/cleans3Public.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/* eslint-disable no-restricted-syntax */
const readline = require('readline');
// eslint-disable-next-line import/no-extraneous-dependencies
const { S3Client, ListObjectsV2Command, DeleteObjectsCommand } = require('@aws-sdk/client-s3');
const { STSClient, GetSessionTokenCommand } = require('@aws-sdk/client-sts');

const S3REGION = 'us-west-2';
const ROLE_ARN = process.env.AWS_ROLE_ARN;
const ROLE_SESSION_NAME = 'S3CleanupSession';

async function* listObjects(s3, params) {
let isTruncated = false;
let token;
do {
const command = new ListObjectsV2Command({ ...params, ContinuationToken: token });
// eslint-disable-next-line no-await-in-loop
const response = await s3.send(command);
yield response.Contents;
({ IsTruncated: isTruncated, NextContinuationToken: token } = response);
} while (isTruncated);
}

function askQuestion(query) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});

return new Promise((resolve) => {
rl.question(query, (ans) => {
rl.close();
resolve(ans);
});
});
}

async function getTemporaryCredentials() {
const stsClient = new STSClient({ region: S3REGION });

const params = {
RoleArn: ROLE_ARN,
RoleSessionName: ROLE_SESSION_NAME,
DurationSeconds: 3600,
};

try {
const command = new GetSessionTokenCommand(params);
const response = await stsClient.send(command);
return response.Credentials;
} catch (err) {
console.error('Error assuming role:', err);
throw err;
}
}

async function main() {
const bucket = process.argv[2];
const s3Path = process.argv[3];

if (!bucket || !s3Path) {
console.log('Usage: node cleans3.js <bucket> <path>');
process.exit(1);
}

const tempCredentials = await getTemporaryCredentials();

const s3 = new S3Client({
region: S3REGION,
credentials: {
accessKeyId: tempCredentials.AccessKeyId,
secretAccessKey: tempCredentials.SecretAccessKey,
sessionToken: tempCredentials.SessionToken,
},
forcePathStyle: true,
});

const params = { Bucket: bucket, Prefix: s3Path, MaxKeys: 1000 };

let totalSize = 0;
const toBeDeleted = {
Bucket: bucket,
Delete: {
Objects: [],
Quiet: false,
},
};

for await (const contents of listObjects(s3, params)) {
if (contents === undefined || contents.length === 0) {
console.log('No objects to delete.');
return; // Skip to next iteration if current is empty
}

for (const obj of contents) {
totalSize += obj.Size;
console.log(`${obj.Key}, ${obj.LastModified}, ${obj.Size}`);
toBeDeleted.Delete.Objects.push({ Key: obj.Key });
}
}

if (toBeDeleted.Delete.Objects.length > 0) {
const answer = await askQuestion('Are you sure you want to delete these files? (yes/no): ');
if (answer.toLowerCase() === 'yes') {
const deleteCommand = new DeleteObjectsCommand(toBeDeleted);
await s3.send(deleteCommand);
toBeDeleted.Delete.Objects = [];
console.log('Files deleted successfully.');
} else {
console.log('Deletion canceled.');
}
} else {
console.log('No files to delete.');
}

console.log(`Total Size: ${totalSize}`);
}

main();
139 changes: 139 additions & 0 deletions libs/screenshot/uploads3Public.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// eslint-disable-next-line import/no-extraneous-dependencies
const { S3Client, PutObjectCommand } = require('@aws-sdk/client-s3');
const { STSClient, GetSessionTokenCommand } = require('@aws-sdk/client-sts');
const fs = require('fs');
const path = require('path');
const { validatePath } = require('./utils.js');

const S3REGION = 'us-west-2';
const S3BUCKET = 'nala-test-automation-screenshots';
const ROLE_ARN = process.env.AWS_ROLE_ARN;
const ROLE_SESSION_NAME = 'ScreenshotUploadSession';

const s3Upload = async (s3, params) => {
try {
const command = new PutObjectCommand(params);
const response = await s3.send(command);
return response;
} catch (err) {
console.error('Upload error:', err);
throw err;
}
};

async function getTemporaryCredentials() {
const stsClient = new STSClient({ region: S3REGION });

const params = {
RoleArn: ROLE_ARN,
RoleSessionName: ROLE_SESSION_NAME,
DurationSeconds: 3600,
};

try {
const command = new GetSessionTokenCommand(params);
const response = await stsClient.send(command);
return response.Credentials;
} catch (err) {
console.error('Error assuming role:', err);
throw err;
}
}

async function uploadFile(fileName, s3Bucket, s3Path, s3Key, mimeType) {
const tempCredentials = await getTemporaryCredentials();

const s3 = new S3Client({
region: S3REGION,
credentials: {
accessKeyId: tempCredentials.AccessKeyId,
secretAccessKey: tempCredentials.SecretAccessKey,
sessionToken: tempCredentials.SessionToken,
},
forcePathStyle: true,
});

const baseName = path.basename(fileName);
const key = path.join(s3Path, s3Key || baseName).replace(/\\/g, '/');

const fileContent = fs.readFileSync(validatePath(fileName));

const params = {
Bucket: s3Bucket,
Key: key,
Body: fileContent,
ContentType: mimeType,
};

await s3Upload(s3, params);
}

async function main() {
const dir = process.argv[2] || 'screenshots/milo';
const bucket = S3BUCKET;
const s3Path = '.';

if (!bucket || !s3Path) {
console.log('Usage: node uploads3.js <localPath>');
process.exit(1);
}

const resultsPath = path.join(dir, 'results.json');
const entries = JSON.parse(fs.readFileSync(validatePath(resultsPath)));

console.log(entries);

const mimeType = 'image/png';

Object.keys(entries).forEach(async (key) => {
const entry = entries[key];
if (Array.isArray(entry)) {
entry.forEach(async (item) => {
if (item.a) {
console.log(item.a);
await uploadFile(item.a, bucket, s3Path, item.a, mimeType);
}

if (item.b) {
console.log(item.b);
await uploadFile(item.b, bucket, s3Path, item.b, mimeType);
}

if (item.diff) {
console.log(item.diff);
await uploadFile(item.diff, bucket, s3Path, item.diff, mimeType);
}
});
} else {
if (entry.a) {
console.log(entry.a);
await uploadFile(entry.a, bucket, s3Path, entry.a, mimeType);
}

if (entry.b) {
console.log(entry.b);
await uploadFile(entry.b, bucket, s3Path, entry.b, mimeType);
}

if (entry.diff) {
console.log(entry.diff);
await uploadFile(entry.diff, bucket, s3Path, entry.diff, mimeType);
}
}
});

console.log('Upload results.json');
await uploadFile(resultsPath, bucket, s3Path, resultsPath, 'application/json');

const timestampPath = path.join(dir, 'timestamp.json');

fs.writeFileSync(
validatePath(timestampPath, { forWriting: true }),
JSON.stringify([(new Date()).toLocaleString()], null, 2),
);

console.log('Upload timestamp.json');
await uploadFile(timestampPath, bucket, s3Path, timestampPath, 'application/json');
}

main();
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"homepage": "https://github.com/adobecom/nala#readme",
"dependencies": {
"@aws-sdk/client-s3": "^3.572.0",
"@aws-sdk/client-sts": "^3.572.0",
"@axe-core/playwright": "^4.7.0",
"@playwright/test": "^1.42",
"axe-html-reporter": "^2.2.3",
Expand Down
12 changes: 11 additions & 1 deletion runScreenDiff.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,20 @@ fi

category="$1"

# Only install dependencies if running in GitHub Actions
if [ -n "$GITHUB_ACTIONS" ]; then
echo "*** Installing playwright dependencies ***"
cd "$GITHUB_ACTION_PATH" || exit
npm ci
npx playwright install --with-deps
else
echo "Skipping dependency installation - not running in GitHub Actions"
fi

# Run each command one by one
node run.js -c ${Config} -p ${Project} -g @${category}-screenshots
node libs/screenshot/merge.js screenshots/${category}
node libs/screenshot/compare.mjs screenshots/${category}
node libs/screenshot/uploads3.js screenshots/${category}
node libs/screenshot/uploads3Public.js screenshots/${category}

echo "All commands executed successfully for category: ${category}!"
Loading