Skip to content
Merged
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
d0af05e
update checkout action version to v6 in CLA workflow
yaswant Dec 8, 2025
fe826dc
refactor: enhance CLA check for contributor status in PR branch
yaswant Dec 8, 2025
e78dd86
refactor: update step name for contributor check in CLA workflow
yaswant Dec 8, 2025
fc10ca3
refactor: update ref input handling for CLA verification
yaswant Dec 8, 2025
2bd6f12
refactor: add functionality to delete old CLA-related comments
yaswant Dec 8, 2025
ff15ce5
refactor: improve filtering of CLA-related comments from GitHub Actio…
yaswant Dec 8, 2025
1181bdb
refactor: remove unused ref input and simplify checkout ref handling
yaswant Dec 8, 2025
e2f37e7
refactor: add error handling for deleting old CLA comments
yaswant Dec 8, 2025
48dd503
refactor: enhance error handling for label creation in CLA workflow
yaswant Dec 8, 2025
4e23060
refactor: update CONTRIBUTORS file references to CONTRIBUTORS.md in C…
yaswant Dec 8, 2025
548cddf
refactor: update CLA comment link to point to the correct repository …
yaswant Dec 9, 2025
dcf2c97
Update post message
yaswant Dec 9, 2025
a455d67
Handle the scenario where a contributor has already signed the CLA in…
yaswant Dec 9, 2025
2415cc9
Merge branch 'main' into develop
yaswant Dec 9, 2025
8e563d5
Empty Commit
yaswant Dec 9, 2025
0eeacb5
Refactor CLA workflow to use base SHA for accurate comparison
yaswant Dec 9, 2025
49f528b
Add copyright notice to CLA Checker workflow file
yaswant Dec 9, 2025
91bf7c5
Merge branch 'main' into develop
yaswant Dec 16, 2025
61639ac
remove labelling when cla already signed on base (#46)
james-bruten-mo Dec 17, 2025
61964fe
Remove label (#47)
james-bruten-mo Dec 17, 2025
dc0cdf9
Remove label (#48)
james-bruten-mo Dec 17, 2025
ba7228b
Remove label (#49)
james-bruten-mo Dec 18, 2025
641b29d
update cla action (#50)
james-bruten-mo Dec 19, 2025
ac9a69a
Project edit action (#53)
james-bruten-mo Jan 7, 2026
322090a
add permissions to develop branch action
james-bruten-mo Jan 7, 2026
b57ad63
update permissions syntax
james-bruten-mo Jan 7, 2026
6132c4b
try read-all
james-bruten-mo Jan 7, 2026
7dcbe75
revert to write
james-bruten-mo Jan 7, 2026
05cadd4
test without assigning
james-bruten-mo Jan 7, 2026
c412c32
update secret
james-bruten-mo Jan 7, 2026
3830a9f
reenable assignee
james-bruten-mo Jan 7, 2026
401087e
update to Yashs version
james-bruten-mo Jan 8, 2026
eccbe42
update secrets
james-bruten-mo Jan 8, 2026
d8ee4bb
update secrets
james-bruten-mo Jan 8, 2026
15227f8
update secrets
james-bruten-mo Jan 8, 2026
53f5f40
debug
james-bruten-mo Jan 8, 2026
84ab60d
debug
james-bruten-mo Jan 8, 2026
7222d47
debug
james-bruten-mo Jan 8, 2026
57146df
add brackets
james-bruten-mo Jan 8, 2026
46931a4
remove debug
james-bruten-mo Jan 8, 2026
d7a9da2
remove debug
james-bruten-mo Jan 8, 2026
f3d6a6e
auto add SR
james-bruten-mo Jan 8, 2026
2b68251
auto add sr
james-bruten-mo Jan 8, 2026
bc0ca12
make case insensitive
james-bruten-mo Jan 8, 2026
95da5ef
testing workflow_run
james-bruten-mo Jan 8, 2026
ef6d34b
update
james-bruten-mo Jan 8, 2026
27e53c2
update
james-bruten-mo Jan 8, 2026
fc4e94f
update
james-bruten-mo Jan 8, 2026
ccbc003
debug
james-bruten-mo Jan 8, 2026
0b2d631
update trigger
james-bruten-mo Jan 8, 2026
abb8dd2
add log
james-bruten-mo Jan 8, 2026
43bc9ea
add log
james-bruten-mo Jan 8, 2026
f7dd63b
switch to artifact
james-bruten-mo Jan 8, 2026
6fce635
add token
james-bruten-mo Jan 8, 2026
c972630
add token
james-bruten-mo Jan 8, 2026
2009ac2
add token
james-bruten-mo Jan 8, 2026
753af3b
add token
james-bruten-mo Jan 8, 2026
7101e2c
permissions
james-bruten-mo Jan 8, 2026
11e55a2
extract location
james-bruten-mo Jan 8, 2026
2f9f83f
extract location
james-bruten-mo Jan 8, 2026
8a3c57c
make trigger reusable
james-bruten-mo Jan 8, 2026
94a1d6d
update permissions
james-bruten-mo Jan 9, 2026
b5c7540
update cla action to allow for conflicts
james-bruten-mo Jan 12, 2026
53a2096
syntax
james-bruten-mo Jan 12, 2026
a93a805
syntax
james-bruten-mo Jan 12, 2026
1af96cc
test exists approach
james-bruten-mo Jan 12, 2026
17efe2d
test exists approach
james-bruten-mo Jan 12, 2026
a1f8cf1
test exists approach
james-bruten-mo Jan 12, 2026
62493c4
test exists approach
james-bruten-mo Jan 12, 2026
53731f9
test exists approach
james-bruten-mo Jan 12, 2026
e3df2d4
test exists approach
james-bruten-mo Jan 12, 2026
cfc5a91
use checking of ref
james-bruten-mo Jan 12, 2026
2b50b4e
syntax
james-bruten-mo Jan 12, 2026
79a1ad6
syntax
james-bruten-mo Jan 12, 2026
066db69
syntax
james-bruten-mo Jan 12, 2026
e13050c
syntax
james-bruten-mo Jan 12, 2026
24d6272
syntax
james-bruten-mo Jan 12, 2026
847707a
syntax
james-bruten-mo Jan 12, 2026
61d2d21
debug
james-bruten-mo Jan 12, 2026
2fe9565
debug
james-bruten-mo Jan 12, 2026
94d5d09
remove debug
james-bruten-mo Jan 12, 2026
ade3f19
Merge branch 'main' into develop
james-bruten-mo Jan 15, 2026
428b9ec
simplify logic
james-bruten-mo Jan 15, 2026
7761d23
Update .github/workflows/cla-check.yaml
james-bruten-mo Jan 15, 2026
8e7dfdc
make lowercase
james-bruten-mo Jan 16, 2026
67832a7
Merge branch 'develop' of github.com:MetOffice/growss into develop
james-bruten-mo Jan 16, 2026
678d62a
update label calls
james-bruten-mo Jan 16, 2026
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
131 changes: 87 additions & 44 deletions .github/workflows/cla-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@ jobs:
check-cla:
runs-on: ${{ inputs.runner }}
steps:
# --- Step 1: Check Base Branch ---
- name: Checkout base branch and check for contributor status
- name: Checkout Base Branch
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: ${{ github.ref }}
path: base_branch

- name: Determine if contributor exists in base (new)
- name: Determine if contributor exists in base
id: check_contributor_base
working-directory: ./base_branch
run: |
AUTHOR="${{ github.event.pull_request.user.login }}"
if [ -f "CONTRIBUTORS.md" ]; then
Expand All @@ -47,17 +48,16 @@ jobs:
echo "🔴 CONTRIBUTORS.md file does not exist on base. Proceeding to check PR branch."
fi

# --- Step 2: Check PR Branch ---
- name: Checkout PR branch and check for contributor status
# Always check PR branch to detect if contributor removed themselves
- name: Checkout PR Branch
uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: ${{ github.event.pull_request.head.sha }}
path: pr_branch

- name: Determine if contributor exists in PR branch
id: check_contributor_pr
# Always check PR branch to detect if contributor removed themselves
working-directory: pr_branch
run: |
AUTHOR="${{ github.event.pull_request.user.login }}"
if [ -f "CONTRIBUTORS.md" ]; then
Expand All @@ -73,25 +73,53 @@ jobs:
echo "🔴 CONTRIBUTORS.md file does not exist on PR branch."
fi

- name: Check Merge Ref Exists
id: check_merge_ref
working-directory: ./base_branch
shell: bash
run: |
ref="refs/pull/${{ github.event.number }}/merge"
hash=$(git ls-remote origin $ref)
if [[ -z $hash ]]; then
echo "merge_ref_defined=false" >> $GITHUB_ENV
else
echo "merge_ref_defined=true" >> $GITHUB_ENV
fi

- name: Checkout Merge Branch
if: env.merge_ref_defined == 'true'
id: checkout_merge
uses: actions/checkout@v6
continue-on-error: true
with:
token: ${{ secrets.GITHUB_TOKEN }}
ref: "refs/pull/${{ github.event.number }}/merge"
path: merge_branch

# -- Check if CONTRIBUTORS.md was modified in this PR
- name: Check if CONTRIBUTORS.md was modified in PR
id: check_contributors_modified
run: |
# Fetch the base branch
git fetch origin ${{ github.event.pull_request.base.ref }}
if [[ "$merge_ref_defined" == "false" ]]; then
echo "::warning::Merge conflicts mean the check for modification of a signed CONTRIBUTORS.md file was not completed. Allowing this to pass while conflict exists."
echo "modified=false" >> $GITHUB_OUTPUT
else
cd merge_branch

# Use the base SHA directly for comparison (works with forks)
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
git fetch origin ${{ github.event.pull_request.base.ref }}

CHANGED_FILES=$(git diff --name-only $BASE_SHA..$HEAD_SHA)
# Use the base SHA directly for comparison (works with forks)
BASE_SHA="${{ github.event.pull_request.base.sha }}"

if echo "$CHANGED_FILES" | grep -q "^CONTRIBUTORS.md$"; then
echo "modified=true" >> $GITHUB_OUTPUT
echo "📝 CONTRIBUTORS.md file was modified in this PR."
else
echo "modified=false" >> $GITHUB_OUTPUT
echo "ℹ️ CONTRIBUTORS.md file was NOT modified in this PR."
CHANGED_FILES=$(git diff --name-only $BASE_SHA)

if echo "$CHANGED_FILES" | grep -q "^CONTRIBUTORS.md$"; then
echo "modified=true" >> $GITHUB_OUTPUT
echo "📝 CONTRIBUTORS.md file was modified in this PR."
else
echo "modified=false" >> $GITHUB_OUTPUT
echo "ℹ️ CONTRIBUTORS.md file was NOT modified in this PR."
fi
fi

# -- Step 3: Manage PR Labels, Comments, and Final Status (Consolidated)
Expand All @@ -111,30 +139,47 @@ jobs:
const repo = context.repo.repo;
const author = context.payload.pull_request.user.login;

// Check if contributor was on base but removed themselves from PR
const removedFromPr = signedOnBase && !signedOnPr && contributorsModified;
// CLA is met if: (1) signed on both base and PR, OR (2) signed on base and didn't modify CONTRIBUTORS.md
const cla_met = (signedOnBase && signedOnPr) || (signedOnBase && !contributorsModified);
// Check if contributor was on base but modified the file
// This may be valid but will require an admin to ok it
const invalidModify = signedOnBase && contributorsModified;

// Helper function to create or update a label with a specific color
async function ensureLabel(name, color, description) {
// CLA is met if:
// * Didn't Invalidly Modify the CONTRIBUTORS and
// * signed on either base or PR
const cla_met = !invalidModify && (signedOnBase || signedOnPr);

// Helper function to create or update a label with a specific COLOUR
async function ensureLabel(name, COLOUR, description) {
try {
await github.rest.issues.updateLabel({ owner, repo, name, color, description });
console.log(`Updated label: ${name} with color ${color}`);
await github.rest.issues.updateLabel({
owner: owner,
repo: repo,
name: name,
description: description,
color: COLOUR
});
console.log(`Updated label: ${name} with COLOUR ${COLOUR}`);
} catch (error) {
// If update fails (label doesn't exist), create it
try {
await github.rest.issues.createLabel({ owner, repo, name, color, description });
console.log(`Created new label: ${name} with color ${color}`);
await github.rest.issues.createLabel({
owner: owner,
repo: repo,
name: name,
description: description,
color: COLOUR
});
console.log(`Created new label: ${name} with COLOUR ${COLOUR}`);
} catch (createError) {
console.log(`Error with label ${name}:`, createError.message);
}
}
}

// Define desired colors and descriptions for consistency
const COLOR_SIGNED = '0052cc'; // Blue
const COLOR_REQUIRED = 'b60205'; // Red
// Define desired COLOURs and descriptions for consistency
const COLOUR_SIGNED = '0052cc'; // Blue
const COLOUR_REQUIRED = 'b60205'; // Red
const COLOUR_MODIFIED = 'f56f27'; // Orange

// Helper function to delete old CLA-related comments from this bot
async function deleteOldClaComments() {
Expand Down Expand Up @@ -170,34 +215,33 @@ jobs:
}
}

console.log(`CLA Met: ${cla_met} (Base: ${signedOnBase}, PR: ${signedOnPr}, Modified: ${contributorsModified}, Removed: ${removedFromPr})`);
console.log(`CLA Met: ${cla_met} (Base: ${signedOnBase}, PR: ${signedOnPr}, Modified: ${contributorsModified}, Invalid Modify: ${invalidModify})`);

// Handle case where contributor removed themselves from CONTRIBUTORS file
if (removedFromPr) {
await ensureLabel('cla-required', COLOR_REQUIRED, 'CLA signature is required for this PR.');
console.log('⚠️ Contributor was in base branch but removed from PR branch.');
// Handle case where contributor modified the file when already on it
if (invalidModify) {
await ensureLabel('cla-modified', COLOUR_MODIFIED, 'The CLA has been modified as part of this PR - added by GA');
console.log('⚠️ Contributor was in base branch but has modified the file.');

// Ensure labels are correct
await Promise.allSettled([
github.rest.issues.removeLabel({ owner, repo, issue_number, name: 'cla-signed' }),
github.rest.issues.addLabels({ owner, repo, issue_number, labels: ['cla-required'] })
github.rest.issues.addLabels({ owner, repo, issue_number, labels: ['cla-modified'] })
]);

// Delete old CLA comments before posting new one
await deleteOldClaComments();

// Post warning comment
const commentBody = `⚠️ Hello @${author}!\n\nYour CLA signature was found on the base branch, but you appear to have removed yourself from the _CONTRIBUTORS.md_ file in this PR.\n\nPlease ensure your entry remains in the _CONTRIBUTORS.md_ file. If you have already signed the CLA, you should not remove your details from the file.`;
const commentBody = `⚠️ Hello @${author}!\n\nYour CLA signature was found on the base branch, but you appear to have modified the _CONTRIBUTORS.md_ file in this PR.\n\nPlease do not edit the _CONTRIBUTORS.md_ file. If you have already signed the CLA, revert changes to the file and your signature will be picked up.`;

await github.rest.issues.createComment({ owner, repo, issue_number, body: commentBody });

// Fail the GitHub Action run
console.error("⚠️ Contributor removed themselves from CONTRIBUTORS file.");
console.error("⚠️ Contributor edited the CONTRIBUTORS file when already on base.");
process.exit(1);
}

if (cla_met) {
await ensureLabel('cla-signed', COLOR_SIGNED, 'This contributor has signed the CLA.');

// Different messages based on scenario
if (signedOnBase && !contributorsModified) {
Expand All @@ -209,15 +253,14 @@ jobs:
// Use Promise.allSettled for robust label management
await Promise.allSettled([
github.rest.issues.removeLabel({ owner, repo, issue_number, name: 'cla-required' }),
github.rest.issues.addLabels({ owner, repo, issue_number, labels: ['cla-signed'] })
]);

// Delete old CLA comments since CLA is satisfied
await deleteOldClaComments();

} else if (!signedOnBase && signedOnPr) {
// New contributor signing CLA for the first time
await ensureLabel('cla-signed', COLOR_SIGNED, 'This contributor has signed the CLA.');
await ensureLabel('cla-signed', COLOUR_SIGNED, 'The CLA has been signed as part of this PR - added by GA');
console.log('✅ New contributor has signed the CLA in PR branch.');
await Promise.allSettled([
github.rest.issues.removeLabel({ owner, repo, issue_number, name: 'cla-required' }),
Expand All @@ -228,7 +271,7 @@ jobs:
await deleteOldClaComments();

} else {
await ensureLabel('cla-required', COLOR_REQUIRED, 'CLA signature is required for this PR.');
await ensureLabel('cla-required', COLOUR_REQUIRED, 'The CLA has not yet been signed by the author of this PR - added by GA');
console.log('❌ CLA condition NOT met. Adding required label and ensuring signed label is absent.');

// Ensure labels are correct
Expand Down
Loading