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

feat(infra): check git state in ci #1860

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
29 changes: 21 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,26 @@ jobs:
cache: "yarn"
- name: Install Packages
run: yarn install
- name: Run Tests
run: yarn test
- name: Run Linter
run: yarn lint
# - name: Run Tests
# run: yarn test
# - name: Run Linter
# run: yarn lint
- name: Workarround for build error
run: rm -rf node_modules/@tendermint
- name: Run Build (ensure that build succeeds)
run: yarn build
- name: Run Ceramic Integration Tests
run: yarn test:ceramic-integration
# - name: Run Build (ensure that build succeeds)
# run: yarn build
# - name: Run Ceramic Integration Tests
# run: yarn test:ceramic-integration
- name: Git fetch
run: |
git fetch
git show origin/main:iam/src/static/providerBitMapInfo.json
working-directory: ./iam
- name: Check bitmap against main
run: |
node dist/iam/src/scripts/checkProviderBitMapInfoAgaistMain.js origin/main
working-directory: ./iam
- name: Check not providers are missing from bitmap
run: |
node dist/iam/src/scripts/checkProviderBitMapInfoForMissingProviders.js
working-directory: ./iam
70 changes: 70 additions & 0 deletions iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import dotenv from "dotenv";
dotenv.config();

import { PassportAttestationStamp } from "../utils/easPassportSchema";
import currentBitmap from "../static/providerBitMapInfo.json";
import { difference } from "./utils";

import { exec } from "child_process";

const processArgs = process.argv.slice(2);

if (processArgs.length < 1) {
console.error(

Check warning on line 13 in iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
"This script will check that there are no items removed in the current version of the\n\
when compared to a base revision (for example against origin/main).\n\
\n\
Call this script with the following arguments:\n\
- <baseRevision> - the revision against you want to compare the current providerBitMapInfo.json"
);
process.exit(1);
}

export const checkNoDeletionsInExpectedBitmap = (
expected: PassportAttestationStamp[],
actual: PassportAttestationStamp[]
): boolean => {
const sExpected = new Set(expected.map((item) => `${item.index}:${item.bit}:${item.name}`).sort());
const sActual = new Set(actual.map((item) => `${item.index}:${item.bit}:${item.name}`).sort());

const missingInExpectedSet = difference(sExpected, sActual);

if (missingInExpectedSet.size > 0) {
console.error("Items that have been removed:");

Check warning on line 33 in iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
console.error(JSON.stringify([...missingInExpectedSet], undefined, 2));

Check warning on line 34 in iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
}

return missingInExpectedSet.size === 0;
};

const baseRevision = processArgs[0];
console.log(`Base revision:\n${baseRevision}`);

Check warning on line 41 in iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement

const gitShowCommand = `git show ${baseRevision}:./src/static/providerBitMapInfo.json`;
console.log("running command: ", gitShowCommand);

Check warning on line 44 in iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement

exec(gitShowCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing command: ${error.message}`);

Check warning on line 48 in iam/src/scripts/checkProviderBitMapInfoAgaistMain.ts

View workflow job for this annotation

GitHub Actions / build

Unexpected console statement
process.exit(1);
return;
}

if (stderr) {
console.error(`Command stderr: ${stderr}`);
process.exit(1);
return;
}

console.log(`Command output (old version):\n${stdout}`);
const previousBitmap = JSON.parse(stdout) as PassportAttestationStamp[];

const isBitmapOk = checkNoDeletionsInExpectedBitmap(previousBitmap, currentBitmap);
if (isBitmapOk) {
console.log("Bitmaps are OK!");
process.exit(0);
} else {
console.log("Bitmaps are not OK!");
process.exit(1);
}
});
56 changes: 56 additions & 0 deletions iam/src/scripts/checkProviderBitMapInfoForMissingProviders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import dotenv from "dotenv";
dotenv.config();

import { PassportAttestationStamp, mapBitMapInfo } from "../utils/easPassportSchema";

import currentBitmap from "../static/providerBitMapInfo.json";
import { getPlatformData, difference } from "./utils";

/**
*
* @param expected The expected bitmap. This could be the base version against which we want to compare.
* @param actual An actual (current, new) version of the bitmap. This is what we want to check.
* @returns true / false depending on whether there are any items missing in the expected bitmap
*/
export const checkNoProvidersMissingInExpectedBitmap = (
expected: PassportAttestationStamp[],
actual: PassportAttestationStamp[]
): boolean => {
const sExpected = new Set(expected.map((item) => `${item.index}:${item.bit}:${item.name}`).sort());
const sActual = new Set(actual.map((item) => `${item.index}:${item.bit}:${item.name}`).sort());

const missingInExpectedSet = difference(sActual, sExpected);

if (missingInExpectedSet.size > 0) {
console.error("Items that are not in the expected (old) bitmap:");
console.error(JSON.stringify([...missingInExpectedSet], undefined, 2));
}

return missingInExpectedSet.size === 0;
};

const checkProviderBitMapInfo = (): boolean => {
const stampMetadata = getPlatformData();
const actualBitMapInfo = mapBitMapInfo(stampMetadata);

return checkNoProvidersMissingInExpectedBitmap(currentBitmap, actualBitMapInfo);
};

const isOk = checkProviderBitMapInfo();

try {
if (isOk) {
console.log("Bitmaps are equal!");
process.exit(0);
} else {
console.error(
"*********************************************\n\
* ERROR : Bitmaps are not equal *\n\
*********************************************"
);
process.exit(1);
}
} catch (err) {
console.error(err);
process.exit(1);
}
69 changes: 69 additions & 0 deletions iam/src/scripts/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { PlatformGroupSpec, platforms } from "@gitcoin/passport-platforms";
import { StampMetadata } from "../utils/easPassportSchema";

export type StampData = {
name: string;
description: string;
hash: string;
};

export type GroupData = {
name: string;
stamps: StampData[];
};

export const skipPlatforms = ["ClearText"];

/**
*
* @param s1 a set
* @param s2 another set
* @returns the difference between set s1 - s2
*/
export const difference = (s1: Set<string>, s2: Set<string>): Set<string> => {
return new Set([...s1].filter((x) => !s2.has(x)));
};

export const formatPlatformGroups = (providerConfig: PlatformGroupSpec[]) =>
providerConfig.reduce(
(groups: GroupData[], group: PlatformGroupSpec) => [
...groups,
{
name: group.platformGroup,
stamps: group.providers.map(({ name, title, hash }) => {
if (!hash) {
throw new Error(`No hash defined for ${name}`);
}
return {
name,
hash,
description: title,
};
}),
},
],
[] as GroupData[]
);

export const getPlatformData = (): StampMetadata => {
return Object.entries(platforms).reduce((data, [id, platform]) => {
if (skipPlatforms.includes(id)) return data;

const { name, icon, description, connectMessage } = platform.PlatformDetails;
if (!icon) throw new Error(`No icon defined for ${id}`);

const groups = formatPlatformGroups(platform.ProviderConfig);

return [
...data,
{
id,
name,
icon,
description,
connectMessage,
groups,
},
];
}, [] as StampMetadata);
};
113 changes: 112 additions & 1 deletion iam/src/static/providerBitMapInfo.json
Original file line number Diff line number Diff line change
@@ -1 +1,112 @@
[{"bit":0,"index":0,"name":"SelfStakingBronze"},{"bit":1,"index":0,"name":"SelfStakingSilver"},{"bit":2,"index":0,"name":"SelfStakingGold"},{"bit":3,"index":0,"name":"CommunityStakingBronze"},{"bit":4,"index":0,"name":"CommunityStakingSilver"},{"bit":5,"index":0,"name":"CommunityStakingGold"},{"bit":6,"index":0,"name":"GitcoinContributorStatistics#numGrantsContributeToGte#1"},{"bit":7,"index":0,"name":"GitcoinContributorStatistics#numGrantsContributeToGte#10"},{"bit":8,"index":0,"name":"GitcoinContributorStatistics#numGrantsContributeToGte#25"},{"bit":9,"index":0,"name":"GitcoinContributorStatistics#numGrantsContributeToGte#100"},{"bit":10,"index":0,"name":"GitcoinContributorStatistics#totalContributionAmountGte#10"},{"bit":11,"index":0,"name":"GitcoinContributorStatistics#totalContributionAmountGte#100"},{"bit":12,"index":0,"name":"GitcoinContributorStatistics#totalContributionAmountGte#1000"},{"bit":13,"index":0,"name":"GitcoinContributorStatistics#numGr14ContributionsGte#1"},{"bit":14,"index":0,"name":"GitcoinContributorStatistics#numRoundsContributedToGte#1"},{"bit":15,"index":0,"name":"twitterAccountAgeGte#180"},{"bit":16,"index":0,"name":"twitterAccountAgeGte#365"},{"bit":17,"index":0,"name":"twitterAccountAgeGte#730"},{"bit":18,"index":0,"name":"Discord"},{"bit":19,"index":0,"name":"Google"},{"bit":20,"index":0,"name":"githubAccountCreationGte#90"},{"bit":21,"index":0,"name":"githubAccountCreationGte#180"},{"bit":22,"index":0,"name":"githubAccountCreationGte#365"},{"bit":23,"index":0,"name":"githubContributionActivityGte#30"},{"bit":24,"index":0,"name":"githubContributionActivityGte#60"},{"bit":25,"index":0,"name":"githubContributionActivityGte#120"},{"bit":26,"index":0,"name":"Facebook"},{"bit":27,"index":0,"name":"FacebookProfilePicture"},{"bit":28,"index":0,"name":"Linkedin"},{"bit":29,"index":0,"name":"Ens"},{"bit":30,"index":0,"name":"Brightid"},{"bit":31,"index":0,"name":"Poh"},{"bit":32,"index":0,"name":"ethPossessionsGte#1"},{"bit":33,"index":0,"name":"ethPossessionsGte#10"},{"bit":34,"index":0,"name":"ethPossessionsGte#32"},{"bit":35,"index":0,"name":"FirstEthTxnProvider"},{"bit":36,"index":0,"name":"EthGTEOneTxnProvider"},{"bit":37,"index":0,"name":"EthGasProvider"},{"bit":38,"index":0,"name":"SnapshotVotesProvider"},{"bit":39,"index":0,"name":"SnapshotProposalsProvider"},{"bit":40,"index":0,"name":"NFT"},{"bit":41,"index":0,"name":"ZkSync"},{"bit":42,"index":0,"name":"ZkSyncEra"},{"bit":43,"index":0,"name":"Lens"},{"bit":44,"index":0,"name":"GnosisSafe"},{"bit":45,"index":0,"name":"Coinbase"},{"bit":46,"index":0,"name":"GuildMember"},{"bit":47,"index":0,"name":"GuildAdmin"},{"bit":48,"index":0,"name":"GuildPassportMember"},{"bit":49,"index":0,"name":"Hypercerts"},{"bit":50,"index":0,"name":"PHIActivitySilver"},{"bit":51,"index":0,"name":"PHIActivityGold"},{"bit":52,"index":0,"name":"HolonymGovIdProvider"},{"bit":53,"index":0,"name":"IdenaState#Newbie"},{"bit":54,"index":0,"name":"IdenaState#Verified"},{"bit":55,"index":0,"name":"IdenaState#Human"},{"bit":56,"index":0,"name":"IdenaStake#1k"},{"bit":57,"index":0,"name":"IdenaStake#10k"},{"bit":58,"index":0,"name":"IdenaStake#100k"},{"bit":59,"index":0,"name":"IdenaAge#5"},{"bit":60,"index":0,"name":"IdenaAge#10"},{"bit":61,"index":0,"name":"CivicCaptchaPass"},{"bit":62,"index":0,"name":"CivicUniquenessPass"},{"bit":63,"index":0,"name":"CivicLivenessPass"},{"bit":64,"index":0,"name":"CyberProfilePremium"},{"bit":65,"index":0,"name":"CyberProfilePaid"},{"bit":66,"index":0,"name":"CyberProfileOrgMember"},{"bit":67,"index":0,"name":"GrantsStack3Projects"},{"bit":68,"index":0,"name":"GrantsStack5Projects"},{"bit":69,"index":0,"name":"GrantsStack7Projects"},{"bit":70,"index":0,"name":"GrantsStack2Programs"},{"bit":71,"index":0,"name":"GrantsStack4Programs"},{"bit":72,"index":0,"name":"GrantsStack6Programs"},{"bit":73,"index":0,"name":"TrustaLabs"}]
[
{ "bit": 0, "index": 0, "name": "SelfStakingBronze" },
{ "bit": 1, "index": 0, "name": "SelfStakingSilver" },
{ "bit": 2, "index": 0, "name": "SelfStakingGold" },
{ "bit": 3, "index": 0, "name": "CommunityStakingBronze" },
{ "bit": 4, "index": 0, "name": "CommunityStakingSilver" },
{ "bit": 5, "index": 0, "name": "CommunityStakingGold" },
{
"bit": 6,
"index": 0,
"name": "GitcoinContributorStatistics#numGrantsContributeToGte#1"
},
{
"bit": 7,
"index": 0,
"name": "GitcoinContributorStatistics#numGrantsContributeToGte#10"
},
{
"bit": 8,
"index": 0,
"name": "GitcoinContributorStatistics#numGrantsContributeToGte#25"
},
{
"bit": 9,
"index": 0,
"name": "GitcoinContributorStatistics#numGrantsContributeToGte#100"
},
{
"bit": 10,
"index": 0,
"name": "GitcoinContributorStatistics#totalContributionAmountGte#10"
},
{
"bit": 11,
"index": 0,
"name": "GitcoinContributorStatistics#totalContributionAmountGte#100"
},
{
"bit": 12,
"index": 0,
"name": "GitcoinContributorStatistics#totalContributionAmountGte#1000"
},
{
"bit": 13,
"index": 0,
"name": "GitcoinContributorStatistics#numGr14ContributionsGte#1"
},
{
"bit": 14,
"index": 0,
"name": "GitcoinContributorStatistics#numRoundsContributedToGte#1"
},
{ "bit": 15, "index": 0, "name": "twitterAccountAgeGte#180" },
{ "bit": 16, "index": 0, "name": "twitterAccountAgeGte#365" },
{ "bit": 17, "index": 0, "name": "twitterAccountAgeGte#730" },
{ "bit": 18, "index": 0, "name": "Discord" },
{ "bit": 19, "index": 0, "name": "Google" },
{ "bit": 20, "index": 0, "name": "githubAccountCreationGte#90" },
{ "bit": 21, "index": 0, "name": "githubAccountCreationGte#180" },
{ "bit": 22, "index": 0, "name": "githubAccountCreationGte#365" },
{ "bit": 23, "index": 0, "name": "githubContributionActivityGte#30" },
{ "bit": 24, "index": 0, "name": "githubContributionActivityGte#60" },
{ "bit": 25, "index": 0, "name": "githubContributionActivityGte#120" },
{ "bit": 26, "index": 0, "name": "Facebook" },
{ "bit": 27, "index": 0, "name": "FacebookProfilePicture" },
{ "bit": 28, "index": 0, "name": "Linkedin" },
{ "bit": 29, "index": 0, "name": "Ens" },
{ "bit": 30, "index": 0, "name": "Brightid" },
{ "bit": 31, "index": 0, "name": "Poh" },
{ "bit": 32, "index": 0, "name": "ethPossessionsGte#1" },
{ "bit": 33, "index": 0, "name": "ethPossessionsGte#10" },
{ "bit": 34, "index": 0, "name": "ethPossessionsGte#32" },
{ "bit": 35, "index": 0, "name": "FirstEthTxnProvider" },
{ "bit": 36, "index": 0, "name": "EthGTEOneTxnProvider" },
{ "bit": 37, "index": 0, "name": "EthGasProvider" },
{ "bit": 38, "index": 0, "name": "SnapshotVotesProvider" },
{ "bit": 39, "index": 0, "name": "SnapshotProposalsProvider" },
{ "bit": 40, "index": 0, "name": "NFT" },
{ "bit": 41, "index": 0, "name": "ZkSync" },
{ "bit": 42, "index": 0, "name": "ZkSyncEra" },
{ "bit": 43, "index": 0, "name": "Lens" },
{ "bit": 44, "index": 0, "name": "GnosisSafe" },
{ "bit": 45, "index": 0, "name": "Coinbase" },
{ "bit": 46, "index": 0, "name": "GuildMember" },
{ "bit": 47, "index": 0, "name": "GuildAdmin" },
{ "bit": 48, "index": 0, "name": "GuildPassportMember" },
{ "bit": 49, "index": 0, "name": "Hypercerts" },
{ "bit": 50, "index": 0, "name": "PHIActivitySilver" },
{ "bit": 51, "index": 0, "name": "PHIActivityGold" },
{ "bit": 52, "index": 0, "name": "HolonymGovIdProvider" },
{ "bit": 53, "index": 0, "name": "IdenaState#Newbie" },
{ "bit": 54, "index": 0, "name": "IdenaState#Verified" },
{ "bit": 55, "index": 0, "name": "IdenaState#Human" },
{ "bit": 56, "index": 0, "name": "IdenaStake#1k" },
{ "bit": 57, "index": 0, "name": "IdenaStake#10k" },
{ "bit": 58, "index": 0, "name": "IdenaStake#100k" },
{ "bit": 59, "index": 0, "name": "IdenaAge#5" },
{ "bit": 60, "index": 0, "name": "IdenaAge#10" },
{ "bit": 61, "index": 0, "name": "CivicCaptchaPass" },
{ "bit": 62, "index": 0, "name": "CivicUniquenessPass" },
{ "bit": 63, "index": 0, "name": "CivicLivenessPass" },
{ "bit": 64, "index": 0, "name": "CyberProfilePremium" },
{ "bit": 65, "index": 0, "name": "CyberProfilePaid" },
{ "bit": 66, "index": 0, "name": "CyberProfileOrgMember" },
{ "bit": 67, "index": 0, "name": "GrantsStack3Projects" },
{ "bit": 68, "index": 0, "name": "GrantsStack5Projects" },
{ "bit": 69, "index": 0, "name": "GrantsStack7Projects" },
{ "bit": 70, "index": 0, "name": "GrantsStack2Programs" },
{ "bit": 71, "index": 0, "name": "GrantsStack4Programs" },
{ "bit": 72, "index": 0, "name": "GrantsStack6Programs" },
{ "bit": 73, "index": 0, "name": "TrustaLabs" }
]
Loading