From 32797ceef4af34ac2548dff9bf9d6de502186d39 Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 30 Apr 2026 20:53:56 +0930 Subject: [PATCH 1/4] Create cla-check.yml --- .github/workflows/cla-check.yml | 91 +++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 .github/workflows/cla-check.yml diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml new file mode 100644 index 0000000..37061f1 --- /dev/null +++ b/.github/workflows/cla-check.yml @@ -0,0 +1,91 @@ +name: CLA contributor check + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +jobs: + check-contributor-membership: + runs-on: ubuntu-latest + permissions: + pull-requests: write + statuses: write + + steps: + - name: Check contributor team membership + id: check + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.ORG_PAT }} + script: | + const author = context.payload.pull_request.user.login; + const org = 'openMF'; + const teams = ['contributors', 'contracted-contributors']; + + // Skip bots + if (context.payload.pull_request.user.type === 'Bot') { + console.log('Bot PR — skipping check'); + return; + } + + // Check membership in either team + let isMember = false; + let matchedTeam = null; + for (const team of teams) { + try { + const resp = await github.rest.teams.getMembershipForUserInOrg({ + org, + team_slug: team, + username: author, + }); + if (resp.data.state === 'active') { + isMember = true; + matchedTeam = team; + break; + } + } catch (e) { + // 404 = not a member, continue + } + } + + if (!isMember) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + body: `👋 Hi @${author} — thank you for your pull request.\n\n` + + `**This PR is currently blocked** because we do not have a Contributor License Agreement (CLA) on file for your GitHub account.\n\n` + + `To get unblocked:\n` + + `1. Contact the Mifos team at contribute@mifos.org\n` + + `2. Complete the CLA signing process\n` + + `3. Once verified, you will be added to the approved contributors list and this PR will be cleared\n\n` + + `_No action is needed from you on this PR until that step is complete._` + }); + + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + labels: ['cla-required'] + }); + + core.setFailed( + `@${author} is not a member of the 'contributors' or 'contracted-contributors' team. ` + + `CLA signature required before this PR can be merged.` + ); + + } else { + console.log(`@${author} is verified via '${matchedTeam}' team ✓`); + + // Remove cla-required label if it was previously added + try { + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.payload.pull_request.number, + name: 'cla-required' + }); + } catch (e) { + // Label may not exist — that's fine + } + } From 27d4e23c028402e11cabca72f2a2ef4dc9627208 Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 1 May 2026 14:00:53 +0930 Subject: [PATCH 2/4] chore: update CLA contributor check workflow [skip ci] --- .github/workflows/cla-check.yml | 52 +++++++++++---------------------- 1 file changed, 17 insertions(+), 35 deletions(-) diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml index 37061f1..16235bc 100644 --- a/.github/workflows/cla-check.yml +++ b/.github/workflows/cla-check.yml @@ -13,7 +13,6 @@ jobs: steps: - name: Check contributor team membership - id: check uses: actions/github-script@v7 with: github-token: ${{ secrets.ORG_PAT }} @@ -22,30 +21,20 @@ jobs: const org = 'openMF'; const teams = ['contributors', 'contracted-contributors']; - // Skip bots if (context.payload.pull_request.user.type === 'Bot') { - console.log('Bot PR — skipping check'); + console.log('Bot PR — skipping CLA check'); return; } - // Check membership in either team let isMember = false; let matchedTeam = null; for (const team of teams) { try { - const resp = await github.rest.teams.getMembershipForUserInOrg({ - org, - team_slug: team, - username: author, + const { data } = await github.rest.teams.getMembershipForUserInOrg({ + org, team_slug: team, username: author, }); - if (resp.data.state === 'active') { - isMember = true; - matchedTeam = team; - break; - } - } catch (e) { - // 404 = not a member, continue - } + if (data.state === 'active') { isMember = true; matchedTeam = team; break; } + } catch (e) { /* 404 = not in this team, try next */ } } if (!isMember) { @@ -53,39 +42,32 @@ jobs: owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, - body: `👋 Hi @${author} — thank you for your pull request.\n\n` + - `**This PR is currently blocked** because we do not have a Contributor License Agreement (CLA) on file for your GitHub account.\n\n` + - `To get unblocked:\n` + - `1. Contact the Mifos team at contribute@mifos.org\n` + - `2. Complete the CLA signing process\n` + - `3. Once verified, you will be added to the approved contributors list and this PR will be cleared\n\n` + - `_No action is needed from you on this PR until that step is complete._` + body: + `👋 Hi @${author} — thank you for your pull request.\n\n` + + `**This PR is currently blocked** because we do not have a Contributor License Agreement (CLA) on file for your GitHub account.\n\n` + + `To get unblocked:\n` + + `1. Contact the Mifos team at contribute@mifos.org\n` + + `2. Complete the CLA signing process\n` + + `3. Once verified you will be added to the approved contributors list and this PR will be cleared\n\n` + + `_No action is needed from you on this PR until that step is complete._` }); - await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, - labels: ['cla-required'] + labels: ['cla-required'], }); - core.setFailed( `@${author} is not a member of the 'contributors' or 'contracted-contributors' team. ` + `CLA signature required before this PR can be merged.` ); - } else { console.log(`@${author} is verified via '${matchedTeam}' team ✓`); - - // Remove cla-required label if it was previously added try { await github.rest.issues.removeLabel({ - owner: context.repo.owner, - repo: context.repo.repo, + owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, - name: 'cla-required' + name: 'cla-required', }); - } catch (e) { - // Label may not exist — that's fine - } + } catch (e) { /* label may not be present — fine */ } } From d96693c1fc2192df28193b65dbb14c170e0751da Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 4 May 2026 11:15:57 +0930 Subject: [PATCH 3/4] chore: update CLA contributor check workflow [skip ci] --- .github/workflows/cla-check.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml index 16235bc..29da97b 100644 --- a/.github/workflows/cla-check.yml +++ b/.github/workflows/cla-check.yml @@ -46,10 +46,9 @@ jobs: `👋 Hi @${author} — thank you for your pull request.\n\n` + `**This PR is currently blocked** because we do not have a Contributor License Agreement (CLA) on file for your GitHub account.\n\n` + `To get unblocked:\n` + - `1. Contact the Mifos team at contribute@mifos.org\n` + + `1. Complete the form at https://mifos.org/about-us/financial-legal/mifos-contributor-agreement\n` + `2. Complete the CLA signing process\n` + - `3. Once verified you will be added to the approved contributors list and this PR will be cleared\n\n` + - `_No action is needed from you on this PR until that step is complete._` + `3. Once verified you will be added to the approved contributors list and this PR check will be cleared` }); await github.rest.issues.addLabels({ owner: context.repo.owner, From 2d75ca6f07bd5fdfb425acc38a7cb976d96f436e Mon Sep 17 00:00:00 2001 From: Tom Date: Thu, 21 May 2026 11:24:16 +0930 Subject: [PATCH 4/4] chore: update CLA contributor check workflow (warn mode) [skip ci] --- .github/workflows/cla-check.yml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cla-check.yml b/.github/workflows/cla-check.yml index 29da97b..5de2cbf 100644 --- a/.github/workflows/cla-check.yml +++ b/.github/workflows/cla-check.yml @@ -44,11 +44,13 @@ jobs: issue_number: context.payload.pull_request.number, body: `👋 Hi @${author} — thank you for your pull request.\n\n` + - `**This PR is currently blocked** because we do not have a Contributor License Agreement (CLA) on file for your GitHub account.\n\n` + - `To get unblocked:\n` + + `**Note:** We do not have a Contributor License Agreement (CLA) on file for your GitHub account. ` + + `Merging is **not blocked** at this time — this repository is in a CLA grace period. ` + + `However, a signed CLA will be required once enforcement is enabled.\n\n` + + `To get your CLA on file:\n` + `1. Complete the form at https://mifos.org/about-us/financial-legal/mifos-contributor-agreement\n` + `2. Complete the CLA signing process\n` + - `3. Once verified you will be added to the approved contributors list and this PR check will be cleared` + `3. Once verified you will be added to the approved contributors list` }); await github.rest.issues.addLabels({ owner: context.repo.owner, @@ -56,9 +58,9 @@ jobs: issue_number: context.payload.pull_request.number, labels: ['cla-required'], }); - core.setFailed( - `@${author} is not a member of the 'contributors' or 'contracted-contributors' team. ` + - `CLA signature required before this PR can be merged.` + core.warning( + `@${author} is not a member of the 'contributors' or 'contracted-contributors' team — ` + + `CLA required (grace period active, merge not blocked).` ); } else { console.log(`@${author} is verified via '${matchedTeam}' team ✓`);