Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
b0fb37b
Attempt incremental run and upload incremental report
saleazer Sep 22, 2024
5ac1db1
Attempt to retrieve incremental report for next run
saleazer Sep 22, 2024
dbbb9cb
Change test name for incremental diff
saleazer Sep 22, 2024
0335290
Add mega logging to JS..
saleazer Sep 22, 2024
4614ddd
Fetch the workflow id
saleazer Sep 22, 2024
a4e26c8
Change paths to reports folder
saleazer Sep 22, 2024
3340e36
Redo logging and change filepath
saleazer Sep 22, 2024
3495c30
Debugging setup
saleazer Sep 22, 2024
c8485d4
Remove useless debugging and fix upload paths
saleazer Sep 22, 2024
bf02e15
Another debug
saleazer Sep 22, 2024
47b7278
Fix typo
saleazer Sep 22, 2024
52209fa
Fix more mistakes
saleazer Sep 22, 2024
20cc584
Tryin' something else, ugh
saleazer Sep 22, 2024
677fb96
Changing tests to test incremental stryker
saleazer Sep 22, 2024
5c59ced
Try full path name for incremental.json
saleazer Sep 22, 2024
2dbc282
Fix the other path too, d'oh
saleazer Sep 22, 2024
56c4892
Add leading slash to urls
saleazer Sep 22, 2024
6579ba1
Fix upload path
saleazer Sep 22, 2024
e63a7bc
Update path logic depending on which run runs
saleazer Sep 22, 2024
66d1acf
Test change to trigger incremental run
saleazer Sep 22, 2024
debb3c3
Update config to stryke all component files
saleazer Sep 22, 2024
91f4f0a
Clean up JS logging
saleazer Sep 22, 2024
a41fd27
Attempt clean stryker run from scratch with no starting file
saleazer Sep 22, 2024
3141a6f
Add back incremental file to workflow
saleazer Sep 22, 2024
00cd11c
Attempt wild component incrementing scheme, haha
saleazer Sep 23, 2024
5909890
Fix mistake in octokit call
saleazer Sep 23, 2024
6db0f9f
Try to fix token issue
saleazer Sep 23, 2024
25e90b2
Fix else/if syntax for stryker run logic
saleazer Sep 23, 2024
3869548
Try to stryke all files that have a .spec file
saleazer Dec 11, 2024
cc7400b
Merge branch 'master' into incremental_strykesss
saleazer Dec 11, 2024
52aadfd
Fix mistakes in .js logic
saleazer Dec 11, 2024
157d630
Change a few logging lines for clarity
saleazer Dec 11, 2024
81f1ba7
Big logic change for stryking + reset count back to 0
saleazer Dec 11, 2024
6c2f1bb
Fix missed renambed variable
saleazer Dec 11, 2024
f02ab56
Fix stupid mistake
saleazer Dec 11, 2024
4d73152
BIG logic change, using stryker.config for files, etc
saleazer Dec 11, 2024
4485e05
Fix missed variable rename
saleazer Dec 11, 2024
079d1ad
Re-implement getting prev count from artifact to continue the stryking
saleazer Dec 11, 2024
df27bba
Adding a comment to inspect what the next run does
saleazer Dec 11, 2024
80c633c
Forcing NULL artifact workflow to test fresh incremental run
saleazer Dec 11, 2024
df263c4
Update files to match glob pattern for stryker.config
saleazer Dec 11, 2024
4cd883a
Add logging to check files
saleazer Dec 11, 2024
79db320
Adding random tests to check progress
saleazer Dec 11, 2024
85b4dd8
Add incrementalFile path to npx command
saleazer Dec 11, 2024
4a2529e
Update logging for clarity and null guard artifact
saleazer Dec 11, 2024
f8fb545
Temporarily remove uploading artifact to test something
saleazer Dec 11, 2024
522654c
Commenting a change to see what the next run does
saleazer Dec 11, 2024
b9c00a4
Move console log to prevent errors
saleazer Dec 11, 2024
9666f7f
Rework logic in artifact download
saleazer Dec 11, 2024
aa0a6a1
Update logging for clarity
saleazer Dec 11, 2024
f56db47
Moar logging
saleazer Dec 11, 2024
d1e78e5
Add more fake tests.. -for science
saleazer Dec 11, 2024
907a8d9
Rename env variables for clarity
saleazer Dec 11, 2024
eb89d78
Re-enable artifact uploading
saleazer Dec 11, 2024
22c077d
Remove commented out line
saleazer Dec 11, 2024
080c376
Attempt with dynamic workflowId
saleazer Dec 16, 2024
c8edac9
Rename workflow and uncomment stuff
saleazer Dec 16, 2024
ad9d6e1
Update logic to search every successful run to find the most recent i…
saleazer Dec 16, 2024
4b913e4
Commenting out uploading the incremental report for testing
saleazer Dec 16, 2024
cc1c71d
Un-commenting out the upload to test new artifact search logic
saleazer Dec 16, 2024
9644cf4
Adding fake tests to app.header to test strykerJS pipeline logic
saleazer Dec 16, 2024
6cb8d28
Format logging info
saleazer Dec 16, 2024
5f45a7a
Update logging and remove commented out code
saleazer Dec 16, 2024
d355a05
Use context to define owner and repo
saleazer Dec 18, 2024
de2c2bf
Try it this way, lol
saleazer Dec 18, 2024
e119f80
Import context
saleazer Dec 18, 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
77 changes: 77 additions & 0 deletions .github/workflows/StrykerJS.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
name: StrykerJS
Copy link
Owner Author

@saleazer saleazer Dec 17, 2024

Choose a reason for hiding this comment

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

First test comment for Webhook POC

Edit: 5th edit


on:
pull_request:
branches: ["master"]

env:
NODE_VERSION: "20.9.0"
INCREMENTAL_PATH: reports/stryker-incremental.json
FILESTOSTRYKE_COUNT: 0
FILESTOSTRYKE: ''

jobs:
strykerJS_testing:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: npm install
run: npm i

- name: Install Temporary Dependencies
run: npm install axios adm-zip @actions/core @actions/github

- name: Download and Extract Incremental File
run: node .github/workflows/download-artifact.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
ARTIFACT_NAME: stryker-incremental

- name: Determine Files to Stryke
run: node .github/workflows/determine-files.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
FILESTOSTRYKE_COUNT: ${{ env.FILESTOSTRYKE_COUNT }}

- name: Run Stryker
run: |
if [ -f /home/runner/work/lets-learn-angular/lets-learn-angular/.github/workflows/extracted_artifact/stryker-incremental.json ]; then
echo "Incremental artifact found, continuing Stryker incremental run."
if [ "$FILESTOSTRYKE" != '' ]; then
echo "Running Stryker incremental with:" && echo "$FILESTOSTRYKE" | tr ' ' '\n'
npx stryker run --incremental --incrementalFile /home/runner/work/lets-learn-angular/lets-learn-angular/.github/workflows/extracted_artifact/stryker-incremental.json
else
echo "No component files were defined to stryke. Unable to run Stryker incremental."
fi
else
echo "No incremental artifact round, running Stryker as initial incremental run."
if [ "$FILESTOSTRYKE" != '' ]; then
echo "Running Stryker with $FILESTOSTRYKE."
npx stryker run --incremental --incrementalFile /home/runner/work/lets-learn-angular/lets-learn-angular/.github/workflows/extracted_artifact/stryker-incremental.json
else
echo "No component files were defined to stryke. Unable to run Stryker."
fi
fi
echo "INCREMENTAL_PATH=/home/runner/work/lets-learn-angular/lets-learn-angular/.github/workflows/extracted_artifact/stryker-incremental.json" >> $GITHUB_ENV

- name: Upload Stryker Incremental Report
uses: actions/upload-artifact@v4
with:
name: stryker-incremental_${{ env.FILESTOSTRYKE_COUNT }}
path: ${{ env.INCREMENTAL_PATH }}

- name: Upload Stryker Coverage Report
uses: actions/upload-artifact@v4
with:
name: stryker-coverage
path: reports/mutation/mutation.html
52 changes: 52 additions & 0 deletions .github/workflows/determine-files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const core = require('@actions/core');
const github = require('@actions/github');

async function getAllFiles(octokit, owner, repo, path) {
const { data: items } = await octokit.rest.repos.getContent({
owner,
repo,
path
});

let files = [];

for (const item of items) {
if (item.type === 'file') {
files.push(item.path);
} else if (item.type === 'dir') {
const subFiles = await getAllFiles(octokit, owner, repo, item.path);
files = files.concat(subFiles);
}
}

return files;
}

(async () => {
try {
const { context } = github;
const octokit = github.getOctokit(process.env.GITHUB_TOKEN);
let prevCount = parseInt(process.env.FILESTOSTRYKE_COUNT, 10);

const allFiles = await getAllFiles(octokit, context.repo.owner, context.repo.repo, 'src/app');
const allFilesWithTests = allFiles
.filter(filename => filename.endsWith('.spec.ts'))
.map(testFile => testFile.replace('.spec.ts', '.ts'));
console.log("All files with tests: ", allFilesWithTests);

if (allFilesWithTests.length === 0) {
console.log('No test files found');
core.exportVariable('FILESTOSTRYKE', '');
core.exportVariable('FILESTOSTRYKE_COUNT', 0);
} else if (allFilesWithTests.length > prevCount) {
const filesToStryke = allFilesWithTests.slice(0, prevCount+1);
core.exportVariable('FILESTOSTRYKE', filesToStryke.join(', '));
core.exportVariable('FILESTOSTRYKE_COUNT', prevCount+1);
} else {
core.exportVariable('FILESTOSTRYKE', allFilesWithTests.join(', '));
}

} catch (error) {
core.setFailed(error.message);
}
})();
110 changes: 110 additions & 0 deletions .github/workflows/download-artifact.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
const axios = require('axios');
const AdmZip = require('adm-zip');
const core = require('@actions/core');
const fs = require('fs');
const path = require('path');
const { context } = require('@actions/github');

const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
const OWNER = `${context.repo.owner}`;
const REPO = `${context.repo.repo}`;
const ARTIFACT_NAME = process.env.ARTIFACT_NAME;

async function getWorkflowId() {
console.log("getWorkflowId");
const url = `https://api.github.com/repos/${OWNER}/${REPO}/actions/workflows`;
const response = await axios.get(url, {
headers: { Authorization: `token ${GITHUB_TOKEN}` }
});
console.log(`getWorkflowId Response status: ${response.status}`);
const workflow = response.data.workflows.find(workflow => workflow.name === process.env.GITHUB_WORKFLOW);
return workflow ? workflow.id : null;
}

async function findLatestIncrementalArtifactId(workflowId) {
if (!workflowId) {
console.error(`Invalid workflowId provided (${workflowId}), unable to find latest incremental artifact`);
return null;
}

console.log(`getWorkflowRuns for ${workflowId}`);
const workflowRunsUrl = `https://api.github.com/repos/${OWNER}/${REPO}/actions/workflows/${workflowId}/runs`;
const response = await axios.get(workflowRunsUrl, {
headers: { Authorization: `token ${GITHUB_TOKEN}` },
params: {
status: 'success'
}
});
console.log(`getWorkflowRuns Response status: ${response.status}`);
const runs = response.data.workflow_runs;

for (let i = 0; i < runs.length; i++) {
const runId = runs[i].id;
console.log(`getArtifacts for run #${i}, runId: ${runId}`);
const artifactsUrl = `https://api.github.com/repos/${OWNER}/${REPO}/actions/runs/${runId}/artifacts`;
const response = await axios.get(artifactsUrl, { headers: { Authorization: `token ${GITHUB_TOKEN}` } });
console.log(`getArtifacts Response status: ${response.status}`);

const artifact = response.data.artifacts.find(artifact => artifact.name.includes(ARTIFACT_NAME));
if (artifact) {
let previousCount = artifact.name.split('_')[1];
core.exportVariable('FILESTOSTRYKE_COUNT', previousCount);
console.log(`artifactId = ${artifact.id}`);
return artifact.id;
}
}
}

async function downloadArtifact(artifactId) {
if (!artifactId) {
console.error(`Invalid artifactId provided (${artifactId}), unable to download artifact`);
return null;
}
console.log(`Valid artifactId provided, downloadArtifact #${artifactId}`);
const url = `https://api.github.com/repos/${OWNER}/${REPO}/actions/artifacts/${artifactId}/zip`;
const response = await axios.get(url, {
headers: {
Authorization: `token ${GITHUB_TOKEN}`
},
responseType: 'arraybuffer'
});

console.log(`downloadArtifact Response status: ${response.status}`);
const zipPath = path.join(__dirname, `${ARTIFACT_NAME}.zip`);
fs.writeFileSync(zipPath, Buffer.from(response.data));
console.log(`zipped artifact path: ${zipPath}`);
return zipPath;
}

function extractArtifact(zipPath) {
if (!zipPath) {
console.error(`Invalid zipPath provided (${zipPath}), unable to extract artifact`);
return null;
}
console.log(`Valid zipPath provided, extractArtifact from: ${zipPath}`);
const zip = new AdmZip(zipPath);
const extractPath = path.join(__dirname, 'extracted_artifact');

zip.extractAllTo(extractPath, true);
console.log(`extracted artifact to: ${extractPath}`);

const artifactFilePath = path.join(extractPath, 'stryker-incremental.json');

if (fs.existsSync(artifactFilePath)) {
console.log(`Artifact file found at: ${artifactFilePath}!`);
} else {
console.error(`Artifact file ${artifactFilePath} not found`);
}
}

(async () => {
try {
const workflowId = await getWorkflowId();
const artifactId = await findLatestIncrementalArtifactId(workflowId);
const zipPath = await downloadArtifact(artifactId);
extractArtifact(zipPath);

} catch (error) {
console.error(`Error: ${error.message}`);
}
})();
37 changes: 0 additions & 37 deletions .github/workflows/scheduled.yml

This file was deleted.

25 changes: 25 additions & 0 deletions src/app/angular-resources/angular-resources.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,29 @@ describe('AngularResourcesComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});

describe("timesTwoTestChange", () => {
it("should return the input value multiplied by two", () => {
let results = component.timesTwo(2);

expect(results).toBe(4);
});
});

describe("timesFourTestChange", () => {
it("should return the input value multiplied by four", () => {
let results = component.timesFour(2);

expect(results).toBe(8);
});
});

describe("timesEightTest", () => {
it("should return the input value multiplied by eight", () => {
let results = component.timesEight(2);

expect(results).toBe(16);
});
});

});
13 changes: 13 additions & 0 deletions src/app/angular-resources/angular-resources.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ export class AngularResourcesComponent implements OnInit {
constructor() { }

ngOnInit(): void {

}

timesTwo(entry: number): number {
return entry * 2;
}

timesFour(entry: number): number {
return entry * 4;
}

timesEight(entry: number): number {
return entry * 8;
}

}
24 changes: 24 additions & 0 deletions src/app/app-footer/app-footer.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,28 @@ describe('AppFooterComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});

describe("timesTwoTestChange", () => {
it("should return the input value multiplied by two", () => {
let results = component.timesTwo(2);

expect(results).toBe(4);
});
});

describe("timesFourTestChange", () => {
it("should return the input value multiplied by four", () => {
let results = component.timesFour(2);

expect(results).toBe(8);
});
});

describe("timesEightTest", () => {
it("should return the input value multiplied by eight", () => {
let results = component.timesEight(2);

expect(results).toBe(16);
});
});
});
11 changes: 11 additions & 0 deletions src/app/app-footer/app-footer.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,15 @@ export class AppFooterComponent implements OnInit {
ngOnInit(): void {
}

timesTwo(entry: number): number {
return entry * 2;
}

timesFour(entry: number): number {
return entry * 4;
}

timesEight(entry: number): number {
return entry * 8;
}
}
Loading