From 27d749333a3dd0f165d8a952585cdbe3fc63bd43 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Wed, 16 Jul 2025 20:45:30 +0200
Subject: [PATCH 01/17] add workflow for trademark addendum
---
.github/workflows/trademark-cla.yml | 339 ++++++++++++++++++++++++++++
1 file changed, 339 insertions(+)
create mode 100644 .github/workflows/trademark-cla.yml
diff --git a/.github/workflows/trademark-cla.yml b/.github/workflows/trademark-cla.yml
new file mode 100644
index 00000000000..8e9eb8d7028
--- /dev/null
+++ b/.github/workflows/trademark-cla.yml
@@ -0,0 +1,339 @@
+name: Integrations - trademark license
+
+on:
+ pull_request:
+ types: [opened, edited, synchronize]
+ issue_comment:
+ types: [created, edited]
+
+permissions: write-all
+
+jobs:
+ enforce-docs-cla:
+ runs-on: ubuntu-latest
+ permissions: write-all
+
+ steps:
+ - name: Debug - Check if secrets exist
+ run: |
+ echo "=== SECRET CHECK ==="
+ if [ -z "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}" ]; then
+ echo "WORKFLOW_AUTH_PUBLIC_APP_ID is empty or not set"
+ else
+ echo "WORKFLOW_AUTH_PUBLIC_APP_ID is set"
+ fi
+
+ if [ -z "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}" ]; then
+ echo "WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY is empty or not set"
+ else
+ echo "WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY is set"
+ fi
+
+ echo "==================="
+
+ - name: Generate Token
+ id: generate-token
+ uses: actions/create-github-app-token@v1
+ with:
+ app-id: "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}"
+ private-key: "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
+
+ - name: Check out code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ # Use the GitHub App token
+ token: ${{ steps.generate-token.outputs.token }}
+
+ - name: Check if docs changed
+ id: docs-changed
+ if: github.event_name == 'pull_request'
+ run: |
+ changed_files=$(git diff --name-only ${{ github.event.pull_request.base.sha}} ${{ github.event.pull_request.head.sha}})
+
+ if echo "$changed_files" | grep -E '^docs/integrations/|^docs/static/' > /dev/null; then
+ echo "docs_changed=true" >> $GITHUB_OUTPUT
+ echo "requires_cla=true" >> $GITHUB_OUTPUT
+ else
+ echo "docs_changed=false" >> $GITHUB_OUTPUT
+ echo "requires_cla=false" >> $GITHUB_OUTPUT
+ fi
+
+ - name: Get PR info for comment events
+ id: pr-info
+ if: github.event_name == 'issue_comment'
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.GITHUB_PAT || secrets.GITHUB_TOKEN }}
+ script: |
+ if (context.payload.issue.pull_request) {
+ const prNumber = context.payload.issue.number;
+ const { data: pr } = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNumber
+ });
+
+ const { data: files } = await github.rest.pulls.listFiles({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNumber
+ });
+
+ const hasDocsChanges = files.some(file =>
+ file.filename.startsWith('docs/integrations/') ||
+ file.filename.startsWith('static/images/')
+ );
+
+ // Check if PR author is a collaborator (safer alternative to org membership)
+ let isClickHouseMember = false;
+ try {
+ const { data: collaboration } = await github.rest.repos.getCollaboratorPermissionLevel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ username: pr.user.login
+ });
+
+ // Consider admin, maintain, or write permissions as "member"
+ isClickHouseMember = ['admin', 'maintain', 'write'].includes(collaboration.permission);
+ } catch (error) {
+ console.log(`Could not determine collaboration status for ${pr.user.login}: ${error.message}`);
+ isClickHouseMember = false;
+ }
+
+ core.setOutput('pr_number', prNumber);
+ core.setOutput('has_docs_changes', hasDocsChanges);
+ core.setOutput('pr_head_sha', pr.head.sha);
+ core.setOutput('pr_author', pr.user.login);
+ core.setOutput('isClickHouseMember', isClickHouseMember);
+
+ return { prNumber, hasDocsChanges, headSha: pr.head.sha, author: pr.user.login, isClickHouseMember };
+ }
+
+ return null;
+
+ - name: Post CLA comment and block merge
+ if: |
+ ((github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') ||
+ (github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true'))
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.CLA_BOT_TOKEN }}
+ script: |
+ let prNumber, prAuthor;
+
+ if (context.eventName == 'pull_request') {
+ prNumber = context.issue.number;
+ prAuthor = '${{ github.event.pull_request.user.login }}';
+ } else {
+ prNumber = ${{ steps.pr-info.outputs.pr_number || 'null' }};
+ prAuthor = '${{ steps.pr-info.outputs.pr_author }}';
+ }
+
+ if (!prNumber || !prAuthor) {
+ console.log('Missing PR number or author, skipping...');
+ return;
+ }
+
+ console.log(`Processing PR #${prNumber} for author: ${prAuthor}`);
+
+ try {
+ // Check if CLA comment already exists
+ const comments = await github.rest.issues.listComments({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ });
+
+ const existingClaComment = comments.data.find(comment =>
+ (comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
+ comment.body.includes('CLA Agreement Required - MERGE BLOCKED')
+ );
+
+ if (!existingClaComment && context.eventName === 'pull_request') {
+ const claText = `# CLA Agreement Required - MERGE BLOCKED
+
+ # Trademark License Addendum
+
+
+ Click to see Trademark License Addendum
+
+ This Trademark License Addendum ("Addendum") shall, if You have opted
+ in by checking the appropriate box that references this Addendum,
+ supplement the terms of the Individual Contributor License Agreement
+ between You and the Company ("Agreement"). Capitalized terms not
+ defined herein shall have the meanings ascribed to them in the
+ Agreement.
+
+ 1. Grant of Trademark License. Subject to the terms and conditions
+ of this Addendum, You grant to the Company a revocable, worldwide,
+ non-exclusive, non-sublicensable (except for contractors or agents
+ acting on the Company's behalf, for whose compliance with this
+ Addendum Company agrees to be responsible), royalty-free, and non-transferable
+ right to display the Partner Trademarks, solely for the purpose of
+ marketing and promoting your Contribution (i) on the Company's website
+ and in any Company in-product integrations page; and (ii) in
+ marketing, sales, and product materials for Company products.
+ "Partner Trademarks" mean Your employer's name and any employer
+ brand features (e.g., logo) you submit to the Company in connection with your
+ Contribution.
+ 2. Legal authority. You represent that you are legally entitled to
+ grant the above license. If your employer(s) has rights to
+ intellectual property in the Partner Trademarks, you represent that
+ you have received permission to grant the above license on behalf
+ of that employer, or that your employer has executed a separate
+ agreement with the Company concerning the subject matter of this
+ Addendum.
+ 3. Conditions. The license in Section 1 is subject to the following
+ conditions:
+ i. The Company shall use the Partner Trademarks in accordance with
+ any reasonable trademark usage guidelines You provide;
+ ii. You may revoke this license at any time upon thirty (30) days'
+ written notice to the Company, after which the Company shall use
+ commercially reasonable efforts to cease all further public
+ use of the Partner Trademarks (but may maintain uses in archived
+ web pages, changelogs, and previously distributed materials).
+ iii. The Company acknowledges and agrees that it does not own the
+ Partner Trademarks and that all goodwill derived from the use
+ of the Partner Trademarks inures solely to benefit of the
+ Partner Trademarks' owner(s).
+ iv. The Company shall use the Partner Trademarks in a professional
+ manner consistent with industry standards and shall not use
+ them in any way that would reasonably be expected to diminish
+ their value or harm the reputation of the Partner Trademarks'
+ owner(s). The Company's use of Partner Trademarks shall not
+ imply endorsement, sponsorship, or affiliation beyond the
+ existence of the Contribution in the Company's integration program.
+ v. The Company will not use the Partner Trademarks in connection
+ with search engine rankings, ad word purchases, or as part of a
+ trade name, business name, or Internet domain name.
+
+
+
+ **To unblock this PR, reply with exactly:**
+
+ \`\`\`
+ I have read and agree to the Contributor License Agreement.
+ CLA-SIGNATURE: ${prAuthor}
+ \`\`\``;
+
+ console.log('Creating CLA comment...');
+ await github.rest.issues.createComment({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: claText
+ });
+
+ console.log('Adding labels...');
+ await github.rest.issues.addLabels({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ labels: ['cla-required', 'docs-changes']
+ });
+
+ console.log('CLA comment and labels added successfully');
+ } else {
+ console.log('CLA comment already exists or not a pull request event');
+ }
+ } catch (error) {
+ console.error('Error in CLA comment step:', error);
+ throw error;
+ }
+
+ - name: Check CLA agreement and manage merge blocking
+ if: |
+ ((github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') ||
+ (github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true'))
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ secrets.CLA_BOT_TOKEN }}
+ script: |
+ let prNumber, prHeadSha, prAuthor;
+
+ if (context.eventName === 'pull_request') {
+ prNumber = context.issue.number;
+ prHeadSha = '${{ github.event.pull_request.head.sha }}';
+ prAuthor = '${{ github.event.pull_request.user.login }}';
+ } else {
+ prNumber = ${{ steps.pr-info.outputs.pr_number || 'null' }};
+ prHeadSha = '${{ steps.pr-info.outputs.pr_head_sha }}';
+ prAuthor = '${{ steps.pr-info.outputs.pr_author }}';
+ }
+
+ if (!prNumber) {
+ console.log('No PR number found, skipping...');
+ return;
+ }
+
+ console.log(`Checking CLA agreement for PR #${prNumber}, author: ${prAuthor}`);
+
+ try {
+ // Get all comments to check for CLA agreement
+ const comments = await github.rest.issues.listComments({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ });
+
+ const claAgreed = comments.data.some(comment => {
+ return comment.user.login === prAuthor &&
+ comment.body.includes('I have read and agree to the Contributor License Agreement') &&
+ comment.body.includes(`CLA-SIGNATURE: ${prAuthor}`);
+ });
+
+ if (claAgreed) {
+ console.log('CLA agreement found, removing blocking labels...');
+
+ // CLA agreed - remove blocking labels and add approval
+ try {
+ await github.rest.issues.removeLabel({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: 'cla-required'
+ });
+ } catch (e) {
+ console.log('Label cla-required not found or already removed');
+ }
+
+ await github.rest.issues.addLabels({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ labels: ['cla-signed']
+ });
+
+ // Post confirmation
+ const confirmationExists = comments.data.some(comment =>
+ (comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
+ comment.body.includes('CLA Agreement Confirmed')
+ );
+
+ if (!confirmationExists) {
+ await github.rest.issues.createComment({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ body: `## CLA Agreement Confirmed
+
+ Thank you @${prAuthor}! Your response has been recorded.
+
+ **Status:** Approved
+ **Date:** ${new Date().toISOString()}
+
+ This PR is now unblocked and can proceed with normal review!`
+ });
+ }
+
+ console.log('CLA processing completed successfully');
+ } else {
+ console.log('CLA not agreed, keeping PR blocked');
+ // CLA not agreed - keep it blocked
+ core.setFailed('Documentation CLA agreement required before merge');
+ }
+ } catch (error) {
+ console.error('Error in CLA agreement check:', error);
+ throw error;
+ }
From 58b8e38863bb8ce5973bdabc7cfeda195c33974b Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Wed, 16 Jul 2025 20:52:02 +0200
Subject: [PATCH 02/17] introduce a fake change
---
.../made-up-integration-for-test.md | 13 +++++++++++++
sidebars.js | 1 +
.../integrations/data-visualization/img.png | Bin 0 -> 13758 bytes
3 files changed, 14 insertions(+)
create mode 100644 docs/integrations/data-visualization/made-up-integration-for-test.md
create mode 100644 static/images/integrations/data-visualization/img.png
diff --git a/docs/integrations/data-visualization/made-up-integration-for-test.md b/docs/integrations/data-visualization/made-up-integration-for-test.md
new file mode 100644
index 00000000000..bc25a37fef1
--- /dev/null
+++ b/docs/integrations/data-visualization/made-up-integration-for-test.md
@@ -0,0 +1,13 @@
+---
+sidebar_label: 'ClickClick'
+slug: /integrations/clickclick
+keywords: ['clickhouse', 'ClickClick', 'connect', 'integrate', 'ui', 'embedded']
+description: 'ClickClick is a made up analytics platform with a native ClickHouse integration'
+title: 'Integrating ClickClick with ClickHouse'
+sidebar: 'integrations'
+---
+
+import Image from '@theme/IdealImage';
+import some_image from '@site/static/images/integrations/data-visualization/clickclick.png';
+
+
\ No newline at end of file
diff --git a/sidebars.js b/sidebars.js
index 66230ab576c..7c662e70d37 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -901,6 +901,7 @@ const sidebars = {
"integrations/data-visualization/looker-and-clickhouse",
"integrations/data-visualization/looker-studio-and-clickhouse",
"integrations/data-visualization/luzmo-and-clickhouse",
+ "integrations/data-visualization/made-up-integration-for-test",
"integrations/data-visualization/metabase-and-clickhouse",
"integrations/data-visualization/mitzu-and-clickhouse",
"integrations/data-visualization/omni-and-clickhouse",
diff --git a/static/images/integrations/data-visualization/img.png b/static/images/integrations/data-visualization/img.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce09ab872fb8f9a7820725a910b79f675c2d0b79
GIT binary patch
literal 13758
zcmdseRa6__7cK>g6^dI*(co4fxI>UoT!Om>m(t=CcS&$58r&&b>{r~~iaV4Rr+DGg
z|I>ZGkN0KP%&c|J?D@8?eZC!~uBw2C1HeH+LBWG4f;CZ4Ua&sjmt$c(U(beHrBG1#
z!ysU3Z7-9fFDjKzLptj<>hwJ32$n)xc4{;E#2`x`hb=}rHHfz!9XkY9-H@f8gix*&
z9!v#bf(OHIQVG#8;V-Z?f%MXqLQ0Oaidcf-y|5o{8{(FBg#t%AAcT=9N}mD3
z_WTk6(ToCH%qt?4fJ9&A5!&?dbbbVqD5|#-4op!5+Qb3No|icM|FOhZMKdjFyX)#5
z?g-gkYow0^yoLIk5#C76kERjB_F{(J-}Wo)2+bftcMDq$!BCcW+a9bOQCa3Ir!P7B
zgB&ahg+=xv*|On>3W2r`?!*R*S4+kKggrM`=X|CruyrTyWJSZY3kS0{*hgp-iaEf)$y3^QTDa
zRICMg`a9@YWhb+t>a!;!x=#zIOEr(fr{|KlL7Uf4-v#k=g+$+&ux=)ZwTobj78KDNZ|bmUe~Yg%hJ#Z-L}#Mh?`_(N@!BZWbLyS^T;LpM?p7w|M
zPXHc>5dE!kSY#d(mf
z5V--b4?<1d90P&3bx$IG4_WKxRV2YgbFS#YRp_>dk~bZn0@H5G98@Q}
z$s1{PYf1^g%${xr0#^bii@<|(2Cd3W$8N=Y)=W`xKTtJ2JM8aZjbB+JWsh~@)IkMcHd2B%8v`N?S3foN
z{W~#wRr0Qo58;oKd6E8so|%|T>4zah-wcKiYNPg;#?Nj6C;shL<0}_{KwmTLNyJ=>
zD(nA#X!~u->=-S3?^yGhaJ1h3&=D^D#$A1Ixc@h4J&^|8Kt0av)L*k%^8^J1#_!s649~_Rg|9@!(eziYjWr>X(s9=CSYx%Ip=cdv7a1
zMju=hBUrsZhT#Yhe
z+qGOeD(`@C)5ilGT`F*c`7e&^y&gQzeO$&**fB9k*;%vdXgcT!>MU`WnMEF>
z)Mcd-wgE8ZzJrNR8gu_fk}Gy}mVJZj-S;$13R4TSF?Z{10$XD?8ZPI3oiAQbi?Lt&
zeRObvJw1Ixmv9zZ;uBlb@S~HoTdi^b-SqH*vtakTQjWZ%o(g|wiKNSJW^2z#i9Qh{
zn)Mw_EN@gQ{KrN_3K>5@(_`XUJG`6j(zc~R*%55CS5=|{L^E`o6Qwp*>y)}u5o`xb
zO5a}O^EO2{HwITLv^N*cU1;v7#6Lb&pGK{y0?!_A0+eJ$2gVy>1v;|EO{eTgx9r3W036#OOKdrZ5Ap%%j~H=fM>v8oKGs?
zEm&sHB&8k2D+ST9KSyRB)@2$WESg%J^B{fEoVnrgzD21YJ;!p?I$mKd&9IzUKE{GF
z?@WOyA9K&=rna?21b4E|JqgbzqM|>YoK!riQZUk-Hcz*WJxKD;mlNCRDB~rmU3FSO
zfnlywcq3l$Mfbtiww|&&-B3#WDD_P*lefycGp*ITMEait{_eqW&&59zny(VTfrWQ9
z7gy_%#vi2_94m+VnedwZtB}(y6YhG!HZJ?5>40%8a0O66Jz8_UPxFL)N%-(*8~^Lc
z&=?TpN_$r4?t5orY=2PMCSA&|N4=we66*_i4af0_a^H`kzssi)Pj}4n;%O@-`J@Z76R&oORdwRDp=OZX
z3WAFtgGhpE`Fn@+iedRUMGkK95efIR&g(3JlJBi>B*#Qd_?_v4&z8nE*pksbizp7B
zwO|yfXHC?6l~d)mn47&K{w+||TiTM)_a5{MwH4+GyBsfhcqCO|W(_*lhG`Iap{J4J
zzmAjFJkP-Oj3xU?7-bhD)r&)k{eFM8KFe|j6#d7nHG|@541&|*`mOi{gw@qRIJhqvvRaFPw$RNNb~buz?O;Hp}7B1t_#4Y8YhC68M#WJw!?
zUgMY1nXvPxd?y-`HCMJ14w~V%DOdR)4C|vyShXiId%AF
zt2I{q%j0sf-^8P>qV%yk2uUS{
zhUBOj5!EE4*M~Lt{%H+7n{YDr@?R!kp|L{n6k}HD0d1Kmyj@>D3&Uz$GF;~OIFox{
zrf~-jwhK7-*KyN7nGs>^ZD+wFZJk3N*l^(Z?
z_d&dx3zBYArv&8J1}8Ht_)v&_IfN1^jN91V`Da~n3N&|Pve#@>s@bM?WMW5X+*!WD
zx$Il;eV8ik0p!HXf^tpA{VWBSA6HO01ur{+Sk|M(qAmLdss788+Grh|w-zMQWxm
z6gfmL6MXlD&efAhu=2%pevJNIqO7ikX$XSH;a_IB#dJlZ_MAXM$Bp_)!%T>2^s0h
zl3gg-P{)moO}qPoh@`>~sLU&;`+galxUjL;O;yBNXL;cbw2QJ&51ZN)fEqzp3~Gwcc9njIv#d_ywsgk0g}T{y;E-zUxoR!`Bls@BZn)Ap^b+ctiHrMPuzF
z-Hf6-$XPfrip2${@)AD`=YA!J+8vT$XrMO>L!6zN_i>JN&09*Q2Of(E{=1
zu<-6#6k#2^#%ZVOJi2sI-|i_zHfZL^H%5FUB>G+Hhnt0DQ~u+g#N=}+pxncbcmT`v
zckh?O{ZOlyCNHjy1=@o5`*{p^=#Wbd6uZk7zBzN3NzD>PrFM|qyU7HoX`Ujp{DzzE
zt&u_DEa-3jmPiS
z_-PUKzOpW~Y5MRtoQ=-=Gp;!vh1)lb;miE_(jPI}PqR&84Ai?d^OtG;EHczEh1Y#U
zsrOYHZZuz}o15=EfK+kFDV8f0vR-Y88U*I7bT9>L#&FU>>|4xc1mtu0oW*
zUkuQ(l7GBEi~jHk%_1(w2pOK5uAeRVK-&1*8G)Jg&zW8*5^2&;cEmTG=XM^S%s#Qk
z*mfFCz!jsf-%+ytq#8ck)y>|
zzc_xE6*-bR>bFfgJ)IQ_TuOoI0%!AIQ6RSbi~8z1_z=@gMlP0_VtDkd!77)l4(#nY
zNH3QhTbrxpH3`4lg}||4^x!Ruqi9ZV22G0!SLH}rtMjM>C;kX|itV6utpmxX_O|Se
z9n4;inXA3H9@w@W(Ao^9O|DMLH9#WNVqDSj`q7A)HLp%u3t=y=j2Wt^l-X;X;VZ88
z>z*f-U4Uc-lShwx?rkCoDPq4q#UmR8Ms&ZV#j^**N9|p(p3qAY-C_;V4;Y6WTJwda
zL=Y~@edRz-$r=>?qNaUznP1-?r!4G)W^>~IlBzPZ_6=FU%Jb-1vq+5C4jyybsI?IE
z+{Zb{R2vfyCm^fCcR}UYPGO(NH#u`f24GDdy_cQ}t#P^+bp~3&A_5ROJZyR$3Hq72
z=A}2^>Lg*&MJZ}j_U6Uh)*A-UWr=sA*~qI(l`{8Q&+jrZiDvvB5p)Fmop!4)=n&H$
zSxlY`rX$C|IhQgCR(LX2^dyvP(X3zvS2~G)O-j?9#KDj3z6F(*&8k--+PhOpePN;m
zO=@Se8toi@olf+Z34wqNV!7{1djGF?k)92Jcy9S(2>~GbHf^oszVl#BjOL%$@?`YP
zO{t%Y#yk<~r7uAUpQeD$RS7x-JyjUeXpxQ;_Q7!oje+(2fB;z3Utm`OKx4#19gAAy
zNQt;D#nEuXGpN~0$CJj>k&u%j(E3f+VZSL$7e80Hq8!t`V$uRB6Z?9uh!7D=-u%u?
z3MnW3Ej?@K(iZ^`%uH6)1j_Xt@SWjDwD2+;veBBziWNn7KRJw9Y|3gFsI7q3
zoZJ@roAxX{<1bVchd|!?%q6R%H&20aT0Mk`Jn$)f_f34r4s#DfCh2Rjo#Zx
zRhWP3N9Z|Y*THCNYfvTHjCbZEo^~_lW}=8C{9mPP2<^#~D}VGdsGLs_o6_tX?ucR=
zw4F=**EqiyRrpU)gyfn?_1xC2Bnaovw2~&Mb{e$`F2(MGrsi*yd3+s?>b*~`nDJkF
zg%Ip6e_IGxluCo}d2EHNMF*!`+z^D#ZeIqucHRX||94TwacC|^Qi>Z3l$T9pl2#YI
zFCK0>mSiZ#hHUo0DJdc4t0xN;h|}@uf)BZ4xg1sk{#V~>@n#&Bg_swRvDyBUOnaJN
zn!Tsy+nE>5AcK{^znbVUMwwq8w}oO1s>JPDGroFMV8S{x$Z)@#P=k6=$*X_7>&C!j
zU!B)7S{rEKTxD>TZOz5sMC`Y}xt+ii0ozAeCe5lVWGi^Y1Xs|jy`2HcH9V1}s9OM1u9Jl)ie)^Mi}nDhOw=$9?%XC2eXsN#Cl~X~6kpGy
z5`cVDWOQlT3~`;lVMCU?(4wL`@{~vnmW{;wvNJSpJkNQ3L5*(s>#)7L)%m==bb$iq
zRSDZ5hO^7=);VB@aNh?&}WHl-x`39_JuLl7M3aO?acAEKOK}p
zQ3=q?q+)L{H2=3b9yy7eoX$kMb5zzW^nEWU9kO|Q{=RMktPi8`S!)9Qe2V<}U6u4l(Bw9#Dw$P|VD{*p$RjCLr
zV>3Jl2Z(0)q0h8@0x9TD
zAKdn(e$XJZX8}Wtu}SOe=eWeDlyrN*#gQ=%NNl&>y2#<khAJ_wxmAn#3`YNrPD*qkK?x3C$<>!1dMz6S$D~o
zqWk(h(V45tFocvWg$BmtfpQlx8o28i^ju0pYS9x5tXDrU(lTTV++ad8Cpskwh}$V0
zN*eKJki@J9dT5=D3KP;zF63Dk9A;|uPbrp@eQ5mI$Wf_?L)SZ7nzka%B&wm51s~Gt
zy4~*(2*F}L_O(tPrU{*Y#J6HBb$7)Bck}IHB3cK;jTneBptThE=1Q6?HESJCK+RkWset-fxp>og1dGqiv5es<_(mUtd#ncOs^VXLNa(SmCI*|9!MN=46YSv>O5?
ze;n+rqB=y%BgYgxz4;;fOWYL#mYuCc_!XvkLt4~6@jF2t54NTm5;eOsqmtbF@@7)N
zZTCq)rIc#+GRL}3b!3;lQDdDJ^|A*yI}guyeN%ScAAcWDC=(~#7<@CIlM5t~Rgo?E
zIW6NloL_eT(2n$#fuJ$v`ZN(JP0Iuo9=^v?U~6gq;9&Uu`+AMGjMipI;$?JwgWQ-l
zB^a2fJp)a(REhS=bPaDQ2Fi&PFcq0Sm$dI*eKcbGa&ETs+!j^2Z`m)pE*?_bzV4qq
z->BF1n~7GK@Z?+?>$nkP%T!cC&%35~0nx3F)>|OzCv+W?2d;1fQ;X&%`tm%61*r?3
zX5lFMXB@Cpdfyb?g-WJgAi9d8du9EbBrTVfV!Jc00`AeqTY6n2TVkkj_?c==Vt
zN0zZ)$!;KoW(CSlLoykIM@3Dnw;6)%b1Z>8o?LC}T_seLvQ&v`*@KFvJbjT7{CTmph8dp_(;^yT0}a4_(%Y|C&@$r?hA#b6)!ye^
zjZc|s=7teme_1)C5JK#%-1c|>#4@E#j6BW+fHOg;0r@)Z#gyVJw-9jXz3>f_88?Ma
z^?u}Mhh^j}N~cIT^E*doA}zj}18U0F^tV@)n
zl7M^kBp<3JqbO1ec5|-|j%03f*M1kSqt_=IGt&7XNGmL_&6n-LbKdvbvXn^0&_XBJ
z#+|c&=>?DxPtL&HKf*q|>XkfTqN5p3{Bz38a1ebg$o4{+!D%5Kiz+7D%d~+PkDHcT
zXo0;jDdpSx>Jy_%^swC}m@y|&w7y{1xIrdZSqqRvI*onZ?}6;QLK{*&VZAmXW|u<SgCI0QmA@Gln%d
zQi@hF{cX9U5BYISFjbV2xRMRDMc_|gTEKLu*FqkTT)AGBV)R2Oa;tI1?B~VzDtXNu
zrZwr;R>M(Vj)$5z2H_>QsAc8xbE
zO$-u1Z>@$#%|209qU{g8f}b}84Dxr^;zbS(_lkhJ59xBMwff-@`&wmCTpm^qTl3%x
zY4BHdo00H@?ppH6JKqru?6St>ccqB;|J~$92f0ovxhp3|u>>c{uCSd0?688_>}FRi
zXq}xbH?j$Zi)XD}0ckjb{MU*x@R4`b4N@t!ne(2T{A}UrQJ9XbZ@J4FA^#~;Q-SEjEO|DuCvSX=On
zYsu9zrko?+N~p$3i8hg
z)P!lsk-}ILB^u-51ec~RP75W(1KzRkU;8$uE(fEhMzig=!``e#mm^r5#AM^w8c*wM
z?|5fxlm^7qza@{SIgfGOx%u^XmobfpQf2bmiw8}}8LP~u(IWC8SN
zrGCY*xmHE!ii3mzjTYlHZGf*l%&!#5W(%L4A6k_*$^7wYek6QJhk>ks|}*GcIho$=`&VjvC>jcz59L%U`l>wT}H&14W{gzpJ)e6(gst8ggTyHI6@
z_>I^H7#G3npUL1#!+%#Qq>O&a_@y4#rM9H|jy0Ukzf*ljmXU9+O}83u@7_?)>iyq+
zuUO(xLHi`sru1BjNy9RQ;_mJ;k41!L#ltwv_Cb{4sFB&A-el(9`=PYU2$H+E8;zM_+5{Z5!)JLRcX}
zn=^L!P^7p~VZ%;?fo`MLsj8j)N&vOxb!0O<8HcyHMqAs!Y1We}C!NwxAKk!dT3)yD
zmON*!)nMg)yP-A;oNU)x|yKx@q40`D}MDhgk+z`v`m
z_xruQvFq*P>jZ;N1YQ3PU0b5adLjvSy3Kz5`;bb0Jtgeu*utEeW6x1JdyR6tNy}ous=7Fv>Md
zs`%ZcrvvES7!!#@`*(|AW_R2ut@c*oWSr+%Pwzu|XH#9K0E-sk@&!DRH^X%qlScd3
zc~Kcu>`vb%Aa(rXoh}1mp|p%~o0)gKg%euHUV%FiQlSX;LRR$Q5(e{+z#_8nd0@bR
zGC)TwKi3{I|NZ45%619SHF~7J>|72qKGl(lhY}=%RDII+k^A
zrPg<5vQG3s-3JXBgRPQ6U%8nHE56CZfCGMRQB!RYR8$eGJuq7I!}7hOtXiu*WrPRO
z{z&xeKmgzG^qMWrJ_4<)5|7G8e1!e37$n8%*{neWnfYBlf%J8hDupl9)*U^#OL{>^
z?VFNuXi0fhNy4IBXZBlSZjG#xLFu?7A`t`xHG}E^LPK~WTz)DZgbro`oDH0XA|Vo>
zBDG&@9-Ns=idpBEi*7uYjgAR9%X_TUFZdYBQ~;CH{SUpUS~2}Rt1V5v6{2K?9`!i%
zXIE=)8neS^+o^$xXgca3O#a~W<-sa~DD0!*V&ot>BZ7Fd<;vy$f#Vki*ABEkn%Ee<
zY(HUa?3Lk=)Iv-t2VPjZGEChtC>lP=NKIfA
z;#MI2T06?O@AVQKAizxhik2W|h_sXbLVpe>>Ety!bLS)r)1v>9`uck#uXs{XbS6hy
z_$RkB9~ajzpxqA&zn&L@y!uN6F>JWF&!>=ir|)=^(;Rj?Svh>
zix7mGh*?H6U&k;ut>!=5ytVXF4M>k>(2%Wlyc(xB+^fZv7p1%%-T;;$-B!zxD-E)I
z-#0K@a4tU%8?AQ5ZbJ%Iy@5vBCx$yRIFF`?h*sTbD#_zqVkRQZVG~Mm^!0#9H4|~J9a?<
z064?*$3<98WuME?f(VP?%M$@spbseSum$wE2;Zp&&|S9KBe%z$VQA+n`d^xA2k)7Z
z@*%6D`ZXI-#g7_OFFP^$8kitWC#=!(a87or0pTF6r8Xta+LdT?p6=BbIj6=P7d
zdp-eYqCWf(`!5eKN~jeo?oN=9>bbeLxLk5`
zb-Hc==lB$=;?eQOaPHqW>0Z}_l5VOqDNJXEmqu9&t>(EiQ9!dUxKLEzjZ&{2zYir0%eb+V0pU*OfX)jE8~gPhAJuGR=s|7U3nh&05t;3~i-f>w#n|I5+-t$o*lkP^LEXyJ
zus1cO+KSc9Q$KCzdPD50?+&j@r#Rf1BU-SkIYIjd?-f#9av(Jz^gjP||8!6K|8!Og
zOe#Ypd!W&$pxQpcq6xR7H`k#^=Lk54yqQ*LCV|ncbr2DvB5~I
zyL1{mv`m}bi2_YN7D{)SEP84ta#<4xY^|T{PnOg&(YT&=rVBsP`Ws#pf=Fj(J6-+B
zl-0t$D6T}47$EkM-3;h_ygh$$wY_jU2xmx_T1*!}`9zp#QH3r^KN)nBF=ZB2vzFk9Q5FqC2`idiyXkfJ|ZMP*m
zO+q+iF*zeH#sA#f^R}j#xBU~#6C32r&!6=TqMk?J3Hk@X`|+q6AOa$9*Ai-hHfd7qihF{-l(VuVq+%c
zpOv2%PCnHqG;aVAg9NXuj-~7X)-#$e3D0zA3k5KdOcoJO6xb+CkB&pH3hu0e}Q
z-?2;WNBR>I14)|+3=OR>2Gi|hKJ#e$U}kZwp4%vu&TLowV~_uS+ejZhxX4?L!yD{c
zI+!@VP4n?mShM&^-~AEhjA-zpBU9AZk_E=XS%VQ#<~Upp3SrK=A^l
zXHxpr>kK~=N`E{im^uM`KG;6sOZcldt>fp+AND<}p!#Mx)Saw<%Ew-&0!)46cSH=x
zgzZuUrJs51b)U4q*665y;&2##)q^|BXY*tVO;X=OW*>c2SB!!T{$mWx|GA0sWs3Ls
zt~k8#4Y6m-u*YB#U_|`y@7H*ykf@M+r+??hRnXrB=5g~T)9=C{+!nnmY`2>lLlOA$
zib?gYu?Al@H6I_d@Q#)LNgKb|(+uM6&PAGtVTf5wLp(C=<)^S+^pr7T*J|r&UVDDS
zO{(6G^d4LkAp|TtXYn>r{_krVD)k3KCEfix#Cl_h#wj@)4Tr;ka;c9akDlqb-}f(D
zhZg43w~~I#-cX$24e>uy_l2-%)5?X_gD8XZ8Yky^A|Smes^Mgxi*;`ER5F5jKHxc-
zB=VU$C=WF_^)QLi-1+{F|7Y71cA1Hwi1#(UYHRNzcvEzjFkVQ$wk#dxsphUhxh=)5
zu3AxlBP^61dMaBch`26@sLv=DeD_D{8BsTumMEwWEB?f|%JQUwG$^&baKru7*Yoi^=p<%X9y33`6xe`k*%rpG!4wK3jGMXZ`Pyye7eg3iS6s
zb?$`^Bq+CSC21IB3RWY`tp2R{I+dB|1i<(lONg^w4r@*1B4>u619ob6>7n!f%wKYE
zk53w|gL;1(Fw8!qz12Gz!5#~$Eil%&oyr0AD=nocOE-}CE0rU(Xs&484*{!An=!}I
zpfr9Hs)x%Bm^iCS%x1dh2BnX=cvep2?6VIi$@9P37V8ussJCNiQa72brq};@I*p#Yl*-xi7}J49}RIN%+qw^4yJqQ;~5o$tEH9YtETD|Ez_~^@u**
zZaTQZBKSe7IG;o-(X$j3Dh=*?Jn6V^yITk~PHN>$CWEQ*{@R&ro~R^OsTLl1e`jI)
z;$#6-;XwaS`6A_eAb}_@dux1BC02Kc$0@BOrbz9^3Aj2SlyB|o2MDD}E$;&W8VrdlCMPSw5|`~Fz%@&>QK
zil#&qjB(3D&~RJ&&{ewW1IkA)1bi}$)I{+pC3!4h1cO^0*;sz2tt
z%gRS_cXaqoRJcS(S`7=4`qHwv-;=`~_;gLdGj!eC;rE81M3`V`C@S~gz>WL?lE4T3
zOYPp)=YB-)07+1rtvveRKe4>3{^fy2S7L=X7M}IUFdGNz~A)5=oMjHE{tDvEP
zUkXQs($eDLrpyBsL>Kad{r%X~@iy?eKVY*%)xh#kQDW#fi_8ydZhfd&(Qev)tr(gH
zfB1%k1H}G8gpcB>tP{q>LaglTb1qLK`jSpKpWlh?*
Date: Wed, 16 Jul 2025 20:56:12 +0200
Subject: [PATCH 03/17] fix
---
.github/workflows/trademark-cla.yml | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/.github/workflows/trademark-cla.yml b/.github/workflows/trademark-cla.yml
index 8e9eb8d7028..58baa40a94f 100644
--- a/.github/workflows/trademark-cla.yml
+++ b/.github/workflows/trademark-cla.yml
@@ -6,11 +6,13 @@ on:
issue_comment:
types: [created, edited]
+# Set repository-level permissions
permissions: write-all
jobs:
enforce-docs-cla:
runs-on: ubuntu-latest
+ # Job-level permissions (inherits from above but can be more restrictive)
permissions: write-all
steps:
@@ -29,21 +31,38 @@ jobs:
echo "WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY is set"
fi
+ if [ -z "${{ secrets.GITHUB_PAT }}" ]; then
+ echo "GITHUB_PAT is empty or not set"
+ else
+ echo "GITHUB_PAT is set"
+ fi
echo "==================="
- name: Generate Token
id: generate-token
+ continue-on-error: true
uses: actions/create-github-app-token@v1
with:
app-id: "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}"
private-key: "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
+ - name: Debug - Token generation result
+ run: |
+ echo "=== TOKEN GENERATION RESULT ==="
+ echo "Token step outcome: ${{ steps.generate-token.outcome }}"
+ if [ "${{ steps.generate-token.outcome }}" = "success" ]; then
+ echo "GitHub App token generated successfully"
+ else
+ echo "GitHub App token generation failed - will use GITHUB_TOKEN"
+ fi
+ echo "================================="
+
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: 0
- # Use the GitHub App token
- token: ${{ steps.generate-token.outputs.token }}
+ # Use the GitHub App token if available, otherwise fallback to GITHUB_TOKEN
+ token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
- name: Check if docs changed
id: docs-changed
@@ -118,7 +137,7 @@ jobs:
(github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true'))
uses: actions/github-script@v7
with:
- github-token: ${{ secrets.CLA_BOT_TOKEN }}
+ github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
let prNumber, prAuthor;
@@ -248,7 +267,7 @@ jobs:
(github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true'))
uses: actions/github-script@v7
with:
- github-token: ${{ secrets.CLA_BOT_TOKEN }}
+ github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
let prNumber, prHeadSha, prAuthor;
From c508018d78eeb4cbc704d9d1b41aa7248dec2507 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Wed, 16 Jul 2025 21:08:15 +0200
Subject: [PATCH 04/17] Troubleshoot manual rerun
---
.github/workflows/trademark-cla.yml | 66 ++++++++++++++++++++++++++---
1 file changed, 60 insertions(+), 6 deletions(-)
diff --git a/.github/workflows/trademark-cla.yml b/.github/workflows/trademark-cla.yml
index 58baa40a94f..e6a8fa65c97 100644
--- a/.github/workflows/trademark-cla.yml
+++ b/.github/workflows/trademark-cla.yml
@@ -131,6 +131,27 @@ jobs:
return null;
+ - name: Debug - CLA requirement check
+ run: |
+ echo "=== CLA REQUIREMENT DEBUG ==="
+ echo "Event name: ${{ github.event_name }}"
+
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
+ echo "PR event - docs changed: ${{ steps.docs-changed.outputs.docs_changed }}"
+ echo "PR event - requires CLA: ${{ steps.docs-changed.outputs.requires_cla }}"
+ fi
+
+ if [ "${{ github.event_name }}" = "issue_comment" ]; then
+ echo "Comment event - has docs changes: ${{ steps.pr-info.outputs.has_docs_changes }}"
+ echo "Comment event - PR number: ${{ steps.pr-info.outputs.pr_number }}"
+ echo "Comment event - PR author: ${{ steps.pr-info.outputs.pr_author }}"
+ echo "Comment event - is ClickHouse member: ${{ steps.pr-info.outputs.isClickHouseMember }}"
+ fi
+
+ CLA_CONDITION="${{ (github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') || (github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true') }}"
+ echo "CLA workflow will run: $CLA_CONDITION"
+ echo "================================="
+
- name: Post CLA comment and block merge
if: |
((github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') ||
@@ -139,14 +160,19 @@ jobs:
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
+ console.log('=== CLA COMMENT STEP DEBUG ===');
+ console.log('Event name:', context.eventName);
+
let prNumber, prAuthor;
if (context.eventName == 'pull_request') {
prNumber = context.issue.number;
prAuthor = '${{ github.event.pull_request.user.login }}';
+ console.log('PR event - Number:', prNumber, 'Author:', prAuthor);
} else {
prNumber = ${{ steps.pr-info.outputs.pr_number || 'null' }};
prAuthor = '${{ steps.pr-info.outputs.pr_author }}';
+ console.log('Comment event - Number:', prNumber, 'Author:', prAuthor);
}
if (!prNumber || !prAuthor) {
@@ -158,17 +184,21 @@ jobs:
try {
// Check if CLA comment already exists
+ console.log('Fetching existing comments...');
const comments = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
+ console.log(`Found ${comments.data.length} existing comments`);
const existingClaComment = comments.data.find(comment =>
(comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
comment.body.includes('CLA Agreement Required - MERGE BLOCKED')
);
+ console.log('Existing CLA comment found:', !!existingClaComment);
+
if (!existingClaComment && context.eventName === 'pull_request') {
const claText = `# CLA Agreement Required - MERGE BLOCKED
@@ -243,6 +273,7 @@ jobs:
repo: context.repo.repo,
body: claText
});
+ console.log('CLA comment created successfully');
console.log('Adding labels...');
await github.rest.issues.addLabels({
@@ -251,11 +282,11 @@ jobs:
repo: context.repo.repo,
labels: ['cla-required', 'docs-changes']
});
-
- console.log('CLA comment and labels added successfully');
+ console.log('Labels added successfully');
} else {
console.log('CLA comment already exists or not a pull request event');
}
+ console.log('=== END CLA COMMENT STEP DEBUG ===');
} catch (error) {
console.error('Error in CLA comment step:', error);
throw error;
@@ -269,16 +300,21 @@ jobs:
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
+ console.log('=== CLA AGREEMENT CHECK DEBUG ===');
+ console.log('Event name:', context.eventName);
+
let prNumber, prHeadSha, prAuthor;
if (context.eventName === 'pull_request') {
prNumber = context.issue.number;
prHeadSha = '${{ github.event.pull_request.head.sha }}';
prAuthor = '${{ github.event.pull_request.user.login }}';
+ console.log('PR event - Number:', prNumber, 'SHA:', prHeadSha, 'Author:', prAuthor);
} else {
prNumber = ${{ steps.pr-info.outputs.pr_number || 'null' }};
prHeadSha = '${{ steps.pr-info.outputs.pr_head_sha }}';
prAuthor = '${{ steps.pr-info.outputs.pr_author }}';
+ console.log('Comment event - Number:', prNumber, 'SHA:', prHeadSha, 'Author:', prAuthor);
}
if (!prNumber) {
@@ -290,18 +326,31 @@ jobs:
try {
// Get all comments to check for CLA agreement
+ console.log('Fetching all comments for CLA check...');
const comments = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
+ console.log(`Found ${comments.data.length} comments to check`);
const claAgreed = comments.data.some(comment => {
- return comment.user.login === prAuthor &&
- comment.body.includes('I have read and agree to the Contributor License Agreement') &&
- comment.body.includes(`CLA-SIGNATURE: ${prAuthor}`);
+ const isAuthor = comment.user.login === prAuthor;
+ const hasAgreement = comment.body.includes('I have read and agree to the Contributor License Agreement');
+ const hasSignature = comment.body.includes(`CLA-SIGNATURE: ${prAuthor}`);
+
+ if (isAuthor && (hasAgreement || hasSignature)) {
+ console.log(`Found potential CLA comment from ${comment.user.login}:`);
+ console.log('- Has agreement text:', hasAgreement);
+ console.log('- Has signature:', hasSignature);
+ console.log('- Comment body preview:', comment.body.substring(0, 100) + '...');
+ }
+
+ return isAuthor && hasAgreement && hasSignature;
});
+ console.log('CLA agreement status:', claAgreed);
+
if (claAgreed) {
console.log('CLA agreement found, removing blocking labels...');
@@ -313,8 +362,9 @@ jobs:
repo: context.repo.repo,
name: 'cla-required'
});
+ console.log('Removed cla-required label');
} catch (e) {
- console.log('Label cla-required not found or already removed');
+ console.log('Label cla-required not found or already removed:', e.message);
}
await github.rest.issues.addLabels({
@@ -323,12 +373,14 @@ jobs:
repo: context.repo.repo,
labels: ['cla-signed']
});
+ console.log('Added cla-signed label');
// Post confirmation
const confirmationExists = comments.data.some(comment =>
(comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
comment.body.includes('CLA Agreement Confirmed')
);
+ console.log('Confirmation comment exists:', confirmationExists);
if (!confirmationExists) {
await github.rest.issues.createComment({
@@ -344,6 +396,7 @@ jobs:
This PR is now unblocked and can proceed with normal review!`
});
+ console.log('Posted confirmation comment');
}
console.log('CLA processing completed successfully');
@@ -352,6 +405,7 @@ jobs:
// CLA not agreed - keep it blocked
core.setFailed('Documentation CLA agreement required before merge');
}
+ console.log('=== END CLA AGREEMENT CHECK DEBUG ===');
} catch (error) {
console.error('Error in CLA agreement check:', error);
throw error;
From 9c03db6109a64cae7b79380d965f88e9084d936d Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Wed, 16 Jul 2025 21:19:30 +0200
Subject: [PATCH 05/17] approver to add the cla-signed label rather than
waiting for comment
---
.github/workflows/trademark-cla.yml | 158 +++++++++-------------------
1 file changed, 52 insertions(+), 106 deletions(-)
diff --git a/.github/workflows/trademark-cla.yml b/.github/workflows/trademark-cla.yml
index e6a8fa65c97..f64fe6de761 100644
--- a/.github/workflows/trademark-cla.yml
+++ b/.github/workflows/trademark-cla.yml
@@ -3,8 +3,8 @@ name: Integrations - trademark license
on:
pull_request:
types: [opened, edited, synchronize]
- issue_comment:
- types: [created, edited]
+ pull_request_target:
+ types: [labeled]
# Set repository-level permissions
permissions: write-all
@@ -135,27 +135,28 @@ jobs:
run: |
echo "=== CLA REQUIREMENT DEBUG ==="
echo "Event name: ${{ github.event_name }}"
+ echo "Event action: ${{ github.event.action }}"
if [ "${{ github.event_name }}" = "pull_request" ]; then
echo "PR event - docs changed: ${{ steps.docs-changed.outputs.docs_changed }}"
echo "PR event - requires CLA: ${{ steps.docs-changed.outputs.requires_cla }}"
fi
- if [ "${{ github.event_name }}" = "issue_comment" ]; then
- echo "Comment event - has docs changes: ${{ steps.pr-info.outputs.has_docs_changes }}"
- echo "Comment event - PR number: ${{ steps.pr-info.outputs.pr_number }}"
- echo "Comment event - PR author: ${{ steps.pr-info.outputs.pr_author }}"
- echo "Comment event - is ClickHouse member: ${{ steps.pr-info.outputs.isClickHouseMember }}"
+ if [ "${{ github.event_name }}" = "pull_request_target" ]; then
+ echo "Label event - label added: ${{ github.event.label.name }}"
+ echo "Label event - added by: ${{ github.actor }}"
+ echo "Label event - cla-signed added: ${{ steps.cla-signed-check.outputs.cla_signed_added }}"
+ echo "Label event - is authorized: ${{ steps.cla-signed-check.outputs.is_authorized }}"
fi
- CLA_CONDITION="${{ (github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') || (github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true') }}"
- echo "CLA workflow will run: $CLA_CONDITION"
+ POST_CLA_CONDITION="${{ github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true' }}"
+ PROCESS_CLA_CONDITION="${{ github.event_name == 'pull_request_target' && steps.cla-signed-check.outputs.cla_signed_added == 'true' && steps.cla-signed-check.outputs.is_authorized == 'true' }}"
+ echo "Post CLA comment workflow will run: $POST_CLA_CONDITION"
+ echo "Process CLA approval workflow will run: $PROCESS_CLA_CONDITION"
echo "================================="
- name: Post CLA comment and block merge
- if: |
- ((github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') ||
- (github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true'))
+ if: github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
@@ -169,10 +170,6 @@ jobs:
prNumber = context.issue.number;
prAuthor = '${{ github.event.pull_request.user.login }}';
console.log('PR event - Number:', prNumber, 'Author:', prAuthor);
- } else {
- prNumber = ${{ steps.pr-info.outputs.pr_number || 'null' }};
- prAuthor = '${{ steps.pr-info.outputs.pr_author }}';
- console.log('Comment event - Number:', prNumber, 'Author:', prAuthor);
}
if (!prNumber || !prAuthor) {
@@ -280,7 +277,7 @@ jobs:
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
- labels: ['cla-required', 'docs-changes']
+ labels: ['cla-required', 'integrations-with-image-change']
});
console.log('Labels added successfully');
} else {
@@ -292,121 +289,70 @@ jobs:
throw error;
}
- - name: Check CLA agreement and manage merge blocking
- if: |
- ((github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true') ||
- (github.event_name == 'issue_comment' && steps.pr-info.outputs.has_docs_changes == 'true'))
+ - name: Process CLA approval and unblock merge
+ if: github.event_name == 'pull_request_target' && steps.cla-signed-check.outputs.cla_signed_added == 'true' && steps.cla-signed-check.outputs.is_authorized == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
- console.log('=== CLA AGREEMENT CHECK DEBUG ===');
+ console.log('=== CLA APPROVAL PROCESSING DEBUG ===');
console.log('Event name:', context.eventName);
+ console.log('Label added:', '${{ github.event.label.name }}');
- let prNumber, prHeadSha, prAuthor;
+ const prNumber = context.issue.number;
+ const prAuthor = '${{ github.event.pull_request.user.login }}';
- if (context.eventName === 'pull_request') {
- prNumber = context.issue.number;
- prHeadSha = '${{ github.event.pull_request.head.sha }}';
- prAuthor = '${{ github.event.pull_request.user.login }}';
- console.log('PR event - Number:', prNumber, 'SHA:', prHeadSha, 'Author:', prAuthor);
- } else {
- prNumber = ${{ steps.pr-info.outputs.pr_number || 'null' }};
- prHeadSha = '${{ steps.pr-info.outputs.pr_head_sha }}';
- prAuthor = '${{ steps.pr-info.outputs.pr_author }}';
- console.log('Comment event - Number:', prNumber, 'SHA:', prHeadSha, 'Author:', prAuthor);
- }
-
- if (!prNumber) {
- console.log('No PR number found, skipping...');
- return;
- }
-
- console.log(`Checking CLA agreement for PR #${prNumber}, author: ${prAuthor}`);
+ console.log(`Processing CLA approval for PR #${prNumber}, author: ${prAuthor}`);
try {
- // Get all comments to check for CLA agreement
- console.log('Fetching all comments for CLA check...');
+ // Remove the blocking label
+ console.log('Removing cla-required label...');
+ try {
+ await github.rest.issues.removeLabel({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ name: 'cla-required'
+ });
+ console.log('Removed cla-required label successfully');
+ } catch (e) {
+ console.log('Label cla-required not found or already removed:', e.message);
+ }
+
+ // Check if confirmation comment already exists
const comments = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
- console.log(`Found ${comments.data.length} comments to check`);
-
- const claAgreed = comments.data.some(comment => {
- const isAuthor = comment.user.login === prAuthor;
- const hasAgreement = comment.body.includes('I have read and agree to the Contributor License Agreement');
- const hasSignature = comment.body.includes(`CLA-SIGNATURE: ${prAuthor}`);
-
- if (isAuthor && (hasAgreement || hasSignature)) {
- console.log(`Found potential CLA comment from ${comment.user.login}:`);
- console.log('- Has agreement text:', hasAgreement);
- console.log('- Has signature:', hasSignature);
- console.log('- Comment body preview:', comment.body.substring(0, 100) + '...');
- }
- return isAuthor && hasAgreement && hasSignature;
- });
-
- console.log('CLA agreement status:', claAgreed);
-
- if (claAgreed) {
- console.log('CLA agreement found, removing blocking labels...');
-
- // CLA agreed - remove blocking labels and add approval
- try {
- await github.rest.issues.removeLabel({
- issue_number: prNumber,
- owner: context.repo.owner,
- repo: context.repo.repo,
- name: 'cla-required'
- });
- console.log('Removed cla-required label');
- } catch (e) {
- console.log('Label cla-required not found or already removed:', e.message);
- }
+ const confirmationExists = comments.data.some(comment =>
+ (comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
+ comment.body.includes('CLA Agreement Confirmed')
+ );
+ console.log('Confirmation comment exists:', confirmationExists);
- await github.rest.issues.addLabels({
+ if (!confirmationExists) {
+ await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
- labels: ['cla-signed']
- });
- console.log('Added cla-signed label');
-
- // Post confirmation
- const confirmationExists = comments.data.some(comment =>
- (comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
- comment.body.includes('CLA Agreement Confirmed')
- );
- console.log('Confirmation comment exists:', confirmationExists);
+ body: `## CLA Agreement Confirmed
- if (!confirmationExists) {
- await github.rest.issues.createComment({
- issue_number: prNumber,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: `## CLA Agreement Confirmed
-
- Thank you @${prAuthor}! Your response has been recorded.
+ The trademark license agreement has been approved for @${prAuthor}.
**Status:** Approved
**Date:** ${new Date().toISOString()}
+ **Approved by:** @${{ github.actor }}
This PR is now unblocked and can proceed with normal review!`
- });
- console.log('Posted confirmation comment');
- }
-
- console.log('CLA processing completed successfully');
- } else {
- console.log('CLA not agreed, keeping PR blocked');
- // CLA not agreed - keep it blocked
- core.setFailed('Documentation CLA agreement required before merge');
+ });
+ console.log('Posted confirmation comment');
}
- console.log('=== END CLA AGREEMENT CHECK DEBUG ===');
+
+ console.log('CLA approval processing completed successfully');
+ console.log('=== END CLA APPROVAL PROCESSING DEBUG ===');
} catch (error) {
- console.error('Error in CLA agreement check:', error);
+ console.error('Error in CLA approval processing:', error);
throw error;
}
From 63f96bee0f4c68b062636031aed97d269ac1ac87 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Wed, 16 Jul 2025 21:31:04 +0200
Subject: [PATCH 06/17] separate flows
---
.github/workflows/trademark-cla-approval.yml | 151 ++++++++++++++++++
...emark-cla.yml => trademark-cla-notice.yml} | 83 +---------
2 files changed, 153 insertions(+), 81 deletions(-)
create mode 100644 .github/workflows/trademark-cla-approval.yml
rename .github/workflows/{trademark-cla.yml => trademark-cla-notice.yml} (76%)
diff --git a/.github/workflows/trademark-cla-approval.yml b/.github/workflows/trademark-cla-approval.yml
new file mode 100644
index 00000000000..f214fa283fa
--- /dev/null
+++ b/.github/workflows/trademark-cla-approval.yml
@@ -0,0 +1,151 @@
+name: Trademark CLA Approval
+
+on:
+ issues:
+ types: [labeled]
+
+permissions: write-all
+
+jobs:
+ process-cla-approval:
+ runs-on: ubuntu-latest
+ if: github.event.label.name == 'cla-signed'
+
+ steps:
+ - name: Debug - Event info
+ run: |
+ echo "=== CLA APPROVAL DEBUG ==="
+ echo "Event: ${{ github.event_name }}"
+ echo "Action: ${{ github.event.action }}"
+ echo "Label: ${{ github.event.label.name }}"
+ echo "Added by: ${{ github.actor }}"
+ echo "Issue number: ${{ github.event.issue.number }}"
+ echo "Is PR: ${{ github.event.issue.pull_request != null }}"
+ echo "================================="
+
+ - name: Generate Token
+ id: generate-token
+ continue-on-error: true
+ uses: actions/create-github-app-token@v1
+ with:
+ app-id: "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}"
+ private-key: "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
+
+ - name: Process CLA approval
+ if: github.event.issue.pull_request != null
+ uses: actions/github-script@v7
+ with:
+ github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
+ script: |
+ console.log('=== PROCESSING CLA APPROVAL ===');
+ console.log('Actor:', context.actor);
+ console.log('PR/Issue number:', context.issue.number);
+
+ // Check if this is actually a PR
+ if (!context.payload.issue.pull_request) {
+ console.log('This is not a PR, skipping...');
+ return;
+ }
+
+ const prNumber = context.payload.issue.number;
+
+ // Get PR details
+ const { data: pr } = await github.rest.pulls.get({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ pull_number: prNumber
+ });
+
+ console.log('PR author:', pr.user.login);
+
+ // Check if the person adding the label has the right permissions
+ try {
+ const { data: collaboration } = await github.rest.repos.getCollaboratorPermissionLevel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ username: context.actor
+ });
+
+ console.log('Actor permission level:', collaboration.permission);
+
+ // Only admin, maintain, or write permissions can approve CLA
+ const isAuthorized = ['admin', 'maintain', 'write'].includes(collaboration.permission);
+ console.log('Is authorized to approve CLA:', isAuthorized);
+
+ if (!isAuthorized) {
+ console.log('User does not have permission to approve CLA');
+
+ // Remove the label that was added by unauthorized user
+ await github.rest.issues.removeLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ name: 'cla-signed'
+ });
+
+ // Add a comment explaining why the label was removed
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ body: `@${context.actor} Only repository maintainers can approve CLAs by adding the \`cla-signed\` label. The label has been removed.`
+ });
+
+ console.log('Unauthorized approval attempt blocked');
+ return;
+ }
+
+ // Authorized - proceed with approval
+ console.log('Processing authorized CLA approval...');
+
+ // Remove the blocking label
+ try {
+ await github.rest.issues.removeLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ name: 'cla-required'
+ });
+ console.log('Removed cla-required label');
+ } catch (e) {
+ console.log('cla-required label not found or already removed:', e.message);
+ }
+
+ // Check if confirmation comment already exists
+ const comments = await github.rest.issues.listComments({
+ issue_number: prNumber,
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ });
+
+ const confirmationExists = comments.data.some(comment =>
+ (comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
+ comment.body.includes('CLA Agreement Confirmed')
+ );
+
+ if (!confirmationExists) {
+ await github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ body: `## CLA Agreement Confirmed
+
+ The trademark license agreement has been approved for @${pr.user.login}.
+
+ **Status:** Approved
+ **Date:** ${new Date().toISOString()}
+ **Approved by:** @${context.actor}
+
+ This PR is now unblocked and can proceed with normal review!`
+ });
+ console.log('Posted confirmation comment');
+ }
+
+ console.log('CLA approval completed successfully');
+
+ } catch (error) {
+ console.error('Error processing CLA approval:', error);
+ throw error;
+ }
+
+ console.log('=== END CLA APPROVAL PROCESSING ===');
diff --git a/.github/workflows/trademark-cla.yml b/.github/workflows/trademark-cla-notice.yml
similarity index 76%
rename from .github/workflows/trademark-cla.yml
rename to .github/workflows/trademark-cla-notice.yml
index f64fe6de761..02d70ecffc3 100644
--- a/.github/workflows/trademark-cla.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -1,10 +1,8 @@
-name: Integrations - trademark license
+name: Trademark CLA Notice
on:
pull_request:
types: [opened, edited, synchronize]
- pull_request_target:
- types: [labeled]
# Set repository-level permissions
permissions: write-all
@@ -142,17 +140,8 @@ jobs:
echo "PR event - requires CLA: ${{ steps.docs-changed.outputs.requires_cla }}"
fi
- if [ "${{ github.event_name }}" = "pull_request_target" ]; then
- echo "Label event - label added: ${{ github.event.label.name }}"
- echo "Label event - added by: ${{ github.actor }}"
- echo "Label event - cla-signed added: ${{ steps.cla-signed-check.outputs.cla_signed_added }}"
- echo "Label event - is authorized: ${{ steps.cla-signed-check.outputs.is_authorized }}"
- fi
-
POST_CLA_CONDITION="${{ github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true' }}"
- PROCESS_CLA_CONDITION="${{ github.event_name == 'pull_request_target' && steps.cla-signed-check.outputs.cla_signed_added == 'true' && steps.cla-signed-check.outputs.is_authorized == 'true' }}"
echo "Post CLA comment workflow will run: $POST_CLA_CONDITION"
- echo "Process CLA approval workflow will run: $PROCESS_CLA_CONDITION"
echo "================================="
- name: Post CLA comment and block merge
@@ -287,72 +276,4 @@ jobs:
} catch (error) {
console.error('Error in CLA comment step:', error);
throw error;
- }
-
- - name: Process CLA approval and unblock merge
- if: github.event_name == 'pull_request_target' && steps.cla-signed-check.outputs.cla_signed_added == 'true' && steps.cla-signed-check.outputs.is_authorized == 'true'
- uses: actions/github-script@v7
- with:
- github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
- script: |
- console.log('=== CLA APPROVAL PROCESSING DEBUG ===');
- console.log('Event name:', context.eventName);
- console.log('Label added:', '${{ github.event.label.name }}');
-
- const prNumber = context.issue.number;
- const prAuthor = '${{ github.event.pull_request.user.login }}';
-
- console.log(`Processing CLA approval for PR #${prNumber}, author: ${prAuthor}`);
-
- try {
- // Remove the blocking label
- console.log('Removing cla-required label...');
- try {
- await github.rest.issues.removeLabel({
- issue_number: prNumber,
- owner: context.repo.owner,
- repo: context.repo.repo,
- name: 'cla-required'
- });
- console.log('Removed cla-required label successfully');
- } catch (e) {
- console.log('Label cla-required not found or already removed:', e.message);
- }
-
- // Check if confirmation comment already exists
- const comments = await github.rest.issues.listComments({
- issue_number: prNumber,
- owner: context.repo.owner,
- repo: context.repo.repo,
- });
-
- const confirmationExists = comments.data.some(comment =>
- (comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
- comment.body.includes('CLA Agreement Confirmed')
- );
- console.log('Confirmation comment exists:', confirmationExists);
-
- if (!confirmationExists) {
- await github.rest.issues.createComment({
- issue_number: prNumber,
- owner: context.repo.owner,
- repo: context.repo.repo,
- body: `## CLA Agreement Confirmed
-
- The trademark license agreement has been approved for @${prAuthor}.
-
- **Status:** Approved
- **Date:** ${new Date().toISOString()}
- **Approved by:** @${{ github.actor }}
-
- This PR is now unblocked and can proceed with normal review!`
- });
- console.log('Posted confirmation comment');
- }
-
- console.log('CLA approval processing completed successfully');
- console.log('=== END CLA APPROVAL PROCESSING DEBUG ===');
- } catch (error) {
- console.error('Error in CLA approval processing:', error);
- throw error;
- }
+ }
\ No newline at end of file
From cfb44cd084c3dff8b8014edf57ae088b207ae46c Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Wed, 16 Jul 2025 22:00:12 +0200
Subject: [PATCH 07/17] fix approval logic
---
.github/workflows/trademark-cla-approval.yml | 93 +++++++++++++++-----
1 file changed, 70 insertions(+), 23 deletions(-)
diff --git a/.github/workflows/trademark-cla-approval.yml b/.github/workflows/trademark-cla-approval.yml
index f214fa283fa..5a5bb844072 100644
--- a/.github/workflows/trademark-cla-approval.yml
+++ b/.github/workflows/trademark-cla-approval.yml
@@ -1,7 +1,13 @@
-name: Trademark CLA Approval
+name: CLA Approval Handler
on:
- issues:
+ workflow_dispatch:
+ inputs:
+ pr_number:
+ description: 'PR number to approve CLA for'
+ required: true
+ type: string
+ pull_request:
types: [labeled]
permissions: write-all
@@ -9,7 +15,7 @@ permissions: write-all
jobs:
process-cla-approval:
runs-on: ubuntu-latest
- if: github.event.label.name == 'cla-signed'
+ if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'cla-signed'
steps:
- name: Debug - Event info
@@ -17,10 +23,13 @@ jobs:
echo "=== CLA APPROVAL DEBUG ==="
echo "Event: ${{ github.event_name }}"
echo "Action: ${{ github.event.action }}"
- echo "Label: ${{ github.event.label.name }}"
- echo "Added by: ${{ github.actor }}"
- echo "Issue number: ${{ github.event.issue.number }}"
- echo "Is PR: ${{ github.event.issue.pull_request != null }}"
+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+ echo "Manual trigger - PR: ${{ github.event.inputs.pr_number }}"
+ else
+ echo "Label: ${{ github.event.label.name }}"
+ echo "Added by: ${{ github.actor }}"
+ echo "PR number: ${{ github.event.number }}"
+ fi
echo "================================="
- name: Generate Token
@@ -32,22 +41,30 @@ jobs:
private-key: "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
- name: Process CLA approval
- if: github.event.issue.pull_request != null
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
console.log('=== PROCESSING CLA APPROVAL ===');
+ console.log('Event:', context.eventName);
console.log('Actor:', context.actor);
- console.log('PR/Issue number:', context.issue.number);
- // Check if this is actually a PR
- if (!context.payload.issue.pull_request) {
- console.log('This is not a PR, skipping...');
+ let prNumber;
+
+ // Determine PR number
+ if (context.eventName === 'workflow_dispatch') {
+ prNumber = parseInt('${{ github.event.inputs.pr_number }}');
+ console.log('Manual trigger for PR:', prNumber);
+ } else if (context.eventName === 'pull_request') {
+ prNumber = context.payload.pull_request.number;
+ console.log('Label trigger for PR:', prNumber);
+ console.log('Label added:', context.payload.label.name);
+ } else {
+ console.log('Unexpected event type, skipping...');
return;
}
- const prNumber = context.payload.issue.number;
+ console.log('Processing CLA approval for PR:', prNumber);
// Get PR details
const { data: pr } = await github.rest.pulls.get({
@@ -58,7 +75,7 @@ jobs:
console.log('PR author:', pr.user.login);
- // Check if the person adding the label has the right permissions
+ // Check if the person triggering has the right permissions
try {
const { data: collaboration } = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
@@ -75,24 +92,53 @@ jobs:
if (!isAuthorized) {
console.log('User does not have permission to approve CLA');
- // Remove the label that was added by unauthorized user
- await github.rest.issues.removeLabel({
+ // If this was a label event, remove the label
+ if (context.eventName !== 'workflow_dispatch') {
+ await github.rest.issues.removeLabel({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber,
+ name: 'cla-signed'
+ });
+ }
+
+ // Add a comment explaining why the action was blocked
+ await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
- name: 'cla-signed'
+ body: `@${context.actor} Only repository maintainers can approve CLAs. ${context.eventName !== 'workflow_dispatch' ? 'The label has been removed.' : ''}`
});
- // Add a comment explaining why the label was removed
- await github.rest.issues.createComment({
+ console.log('Unauthorized approval attempt blocked');
+ return;
+ }
+
+ // Check if PR has cla-required label
+ const { data: labels } = await github.rest.issues.listLabelsOnIssue({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: prNumber
+ });
+
+ const hasClaMeeded = labels.some(label => label.name === 'cla-required');
+ console.log('PR has cla-required label:', hasClaMeeded);
+
+ if (!hasClaMeeded) {
+ console.log('PR does not have cla-required label, no action needed');
+ return;
+ }
+
+ // Ensure cla-signed label is present
+ const hasClaSigned = labels.some(label => label.name === 'cla-signed');
+ if (!hasClaSigned) {
+ console.log('Adding cla-signed label...');
+ await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
- body: `@${context.actor} Only repository maintainers can approve CLAs by adding the \`cla-signed\` label. The label has been removed.`
+ labels: ['cla-signed']
});
-
- console.log('Unauthorized approval attempt blocked');
- return;
}
// Authorized - proceed with approval
@@ -135,6 +181,7 @@ jobs:
**Status:** Approved
**Date:** ${new Date().toISOString()}
**Approved by:** @${context.actor}
+ **Method:** ${context.eventName === 'workflow_dispatch' ? 'Manual approval' : 'Label approval'}
This PR is now unblocked and can proceed with normal review!`
});
From 127e107d4d0d39be590a28f813a2eb1a218774eb Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Thu, 17 Jul 2025 14:46:37 +0200
Subject: [PATCH 08/17] remove deubgging and make some more improvements
(exclude clickhouse members)
---
.github/workflows/trademark-cla-approval.yml | 42 +--------
.github/workflows/trademark-cla-notice.yml | 90 +++++---------------
2 files changed, 23 insertions(+), 109 deletions(-)
diff --git a/.github/workflows/trademark-cla-approval.yml b/.github/workflows/trademark-cla-approval.yml
index 5a5bb844072..9e770bdefcd 100644
--- a/.github/workflows/trademark-cla-approval.yml
+++ b/.github/workflows/trademark-cla-approval.yml
@@ -18,19 +18,6 @@ jobs:
if: github.event_name == 'workflow_dispatch' || github.event.label.name == 'cla-signed'
steps:
- - name: Debug - Event info
- run: |
- echo "=== CLA APPROVAL DEBUG ==="
- echo "Event: ${{ github.event_name }}"
- echo "Action: ${{ github.event.action }}"
- if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
- echo "Manual trigger - PR: ${{ github.event.inputs.pr_number }}"
- else
- echo "Label: ${{ github.event.label.name }}"
- echo "Added by: ${{ github.actor }}"
- echo "PR number: ${{ github.event.number }}"
- fi
- echo "================================="
- name: Generate Token
id: generate-token
@@ -45,27 +32,17 @@ jobs:
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
- console.log('=== PROCESSING CLA APPROVAL ===');
- console.log('Event:', context.eventName);
- console.log('Actor:', context.actor);
-
let prNumber;
// Determine PR number
if (context.eventName === 'workflow_dispatch') {
prNumber = parseInt('${{ github.event.inputs.pr_number }}');
- console.log('Manual trigger for PR:', prNumber);
} else if (context.eventName === 'pull_request') {
prNumber = context.payload.pull_request.number;
- console.log('Label trigger for PR:', prNumber);
- console.log('Label added:', context.payload.label.name);
} else {
- console.log('Unexpected event type, skipping...');
return;
}
- console.log('Processing CLA approval for PR:', prNumber);
-
// Get PR details
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
@@ -73,7 +50,6 @@ jobs:
pull_number: prNumber
});
- console.log('PR author:', pr.user.login);
// Check if the person triggering has the right permissions
try {
@@ -83,14 +59,10 @@ jobs:
username: context.actor
});
- console.log('Actor permission level:', collaboration.permission);
-
// Only admin, maintain, or write permissions can approve CLA
const isAuthorized = ['admin', 'maintain', 'write'].includes(collaboration.permission);
- console.log('Is authorized to approve CLA:', isAuthorized);
if (!isAuthorized) {
- console.log('User does not have permission to approve CLA');
// If this was a label event, remove the label
if (context.eventName !== 'workflow_dispatch') {
@@ -110,7 +82,6 @@ jobs:
body: `@${context.actor} Only repository maintainers can approve CLAs. ${context.eventName !== 'workflow_dispatch' ? 'The label has been removed.' : ''}`
});
- console.log('Unauthorized approval attempt blocked');
return;
}
@@ -122,17 +93,14 @@ jobs:
});
const hasClaMeeded = labels.some(label => label.name === 'cla-required');
- console.log('PR has cla-required label:', hasClaMeeded);
if (!hasClaMeeded) {
- console.log('PR does not have cla-required label, no action needed');
return;
}
// Ensure cla-signed label is present
const hasClaSigned = labels.some(label => label.name === 'cla-signed');
if (!hasClaSigned) {
- console.log('Adding cla-signed label...');
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
@@ -142,7 +110,6 @@ jobs:
}
// Authorized - proceed with approval
- console.log('Processing authorized CLA approval...');
// Remove the blocking label
try {
@@ -152,9 +119,8 @@ jobs:
issue_number: prNumber,
name: 'cla-required'
});
- console.log('Removed cla-required label');
} catch (e) {
- console.log('cla-required label not found or already removed:', e.message);
+ // Label not found or already removed
}
// Check if confirmation comment already exists
@@ -185,14 +151,8 @@ jobs:
This PR is now unblocked and can proceed with normal review!`
});
- console.log('Posted confirmation comment');
}
- console.log('CLA approval completed successfully');
-
} catch (error) {
- console.error('Error processing CLA approval:', error);
throw error;
}
-
- console.log('=== END CLA APPROVAL PROCESSING ===');
diff --git a/.github/workflows/trademark-cla-notice.yml b/.github/workflows/trademark-cla-notice.yml
index 02d70ecffc3..2bd604f1fa6 100644
--- a/.github/workflows/trademark-cla-notice.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -14,28 +14,6 @@ jobs:
permissions: write-all
steps:
- - name: Debug - Check if secrets exist
- run: |
- echo "=== SECRET CHECK ==="
- if [ -z "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}" ]; then
- echo "WORKFLOW_AUTH_PUBLIC_APP_ID is empty or not set"
- else
- echo "WORKFLOW_AUTH_PUBLIC_APP_ID is set"
- fi
-
- if [ -z "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}" ]; then
- echo "WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY is empty or not set"
- else
- echo "WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY is set"
- fi
-
- if [ -z "${{ secrets.GITHUB_PAT }}" ]; then
- echo "GITHUB_PAT is empty or not set"
- else
- echo "GITHUB_PAT is set"
- fi
- echo "==================="
-
- name: Generate Token
id: generate-token
continue-on-error: true
@@ -44,17 +22,6 @@ jobs:
app-id: "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}"
private-key: "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
- - name: Debug - Token generation result
- run: |
- echo "=== TOKEN GENERATION RESULT ==="
- echo "Token step outcome: ${{ steps.generate-token.outcome }}"
- if [ "${{ steps.generate-token.outcome }}" = "success" ]; then
- echo "GitHub App token generated successfully"
- else
- echo "GitHub App token generation failed - will use GITHUB_TOKEN"
- fi
- echo "================================="
-
- name: Check out code
uses: actions/checkout@v4
with:
@@ -129,62 +96,55 @@ jobs:
return null;
- - name: Debug - CLA requirement check
- run: |
- echo "=== CLA REQUIREMENT DEBUG ==="
- echo "Event name: ${{ github.event_name }}"
- echo "Event action: ${{ github.event.action }}"
-
- if [ "${{ github.event_name }}" = "pull_request" ]; then
- echo "PR event - docs changed: ${{ steps.docs-changed.outputs.docs_changed }}"
- echo "PR event - requires CLA: ${{ steps.docs-changed.outputs.requires_cla }}"
- fi
-
- POST_CLA_CONDITION="${{ github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true' }}"
- echo "Post CLA comment workflow will run: $POST_CLA_CONDITION"
- echo "================================="
-
- name: Post CLA comment and block merge
if: github.event_name == 'pull_request' && steps.docs-changed.outputs.requires_cla == 'true'
uses: actions/github-script@v7
with:
github-token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
script: |
- console.log('=== CLA COMMENT STEP DEBUG ===');
- console.log('Event name:', context.eventName);
-
let prNumber, prAuthor;
if (context.eventName == 'pull_request') {
prNumber = context.issue.number;
prAuthor = '${{ github.event.pull_request.user.login }}';
- console.log('PR event - Number:', prNumber, 'Author:', prAuthor);
}
if (!prNumber || !prAuthor) {
- console.log('Missing PR number or author, skipping...');
return;
}
- console.log(`Processing PR #${prNumber} for author: ${prAuthor}`);
-
try {
+ // Check if user is in @ClickHouse/everyone team
+ let isClickHouseMember = false;
+ try {
+ await github.rest.teams.getMembershipForUserInOrg({
+ org: 'ClickHouse',
+ team_slug: 'everyone',
+ username: prAuthor
+ });
+ isClickHouseMember = true;
+ } catch (error) {
+ // User is not in the team or team doesn't exist
+ isClickHouseMember = false;
+ }
+
+ // Skip CLA requirement for ClickHouse team members
+ if (isClickHouseMember) {
+ return;
+ }
+
// Check if CLA comment already exists
- console.log('Fetching existing comments...');
const comments = await github.rest.issues.listComments({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
});
- console.log(`Found ${comments.data.length} existing comments`);
const existingClaComment = comments.data.find(comment =>
(comment.user.login === 'github-actions[bot]' || comment.user.type === 'Bot') &&
comment.body.includes('CLA Agreement Required - MERGE BLOCKED')
);
- console.log('Existing CLA comment found:', !!existingClaComment);
-
if (!existingClaComment && context.eventName === 'pull_request') {
const claText = `# CLA Agreement Required - MERGE BLOCKED
@@ -194,7 +154,8 @@ jobs:
Click to see Trademark License Addendum
This Trademark License Addendum ("Addendum") shall, if You have opted
- in by checking the appropriate box that references this Addendum,
+ in by replying to the comment that references this Addendum that you
+ have read and agree to theContributor License Agreement Addendum,
supplement the terms of the Individual Contributor License Agreement
between You and the Company ("Agreement"). Capitalized terms not
defined herein shall have the meanings ascribed to them in the
@@ -248,31 +209,24 @@ jobs:
**To unblock this PR, reply with exactly:**
\`\`\`
- I have read and agree to the Contributor License Agreement.
+ I have read and agree to the Contributor License Agreement Addendum.
CLA-SIGNATURE: ${prAuthor}
\`\`\``;
- console.log('Creating CLA comment...');
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: claText
});
- console.log('CLA comment created successfully');
- console.log('Adding labels...');
await github.rest.issues.addLabels({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['cla-required', 'integrations-with-image-change']
});
- console.log('Labels added successfully');
- } else {
- console.log('CLA comment already exists or not a pull request event');
}
- console.log('=== END CLA COMMENT STEP DEBUG ===');
} catch (error) {
console.error('Error in CLA comment step:', error);
throw error;
From 3fe9b560bb742df201340d93af5a4bf2581e9814 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 06:32:01 +0200
Subject: [PATCH 09/17] updates
---
.github/workflows/trademark-cla-approval.yml | 65 ++++++++-
.github/workflows/trademark-cla-notice.yml | 135 ++++++++++---------
2 files changed, 132 insertions(+), 68 deletions(-)
diff --git a/.github/workflows/trademark-cla-approval.yml b/.github/workflows/trademark-cla-approval.yml
index 9e770bdefcd..435756f4c51 100644
--- a/.github/workflows/trademark-cla-approval.yml
+++ b/.github/workflows/trademark-cla-approval.yml
@@ -27,6 +27,12 @@ jobs:
app-id: "${{ secrets.WORKFLOW_AUTH_PUBLIC_APP_ID }}"
private-key: "${{ secrets.WORKFLOW_AUTH_PUBLIC_PRIVATE_KEY }}"
+ - name: Check out code
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ token: ${{ steps.generate-token.outputs.token || secrets.GITHUB_TOKEN }}
+
- name: Process CLA approval
uses: actions/github-script@v7
with:
@@ -92,9 +98,9 @@ jobs:
issue_number: prNumber
});
- const hasClaMeeded = labels.some(label => label.name === 'cla-required');
+ const hasClaNeeded = labels.some(label => label.name === 'cla-required');
- if (!hasClaMeeded) {
+ if (!hasClaNeeded) {
return;
}
@@ -123,6 +129,11 @@ jobs:
// Label not found or already removed
}
+ // Store the manual approval information
+ core.setOutput('pr_number', prNumber);
+ core.setOutput('pr_author', pr.user.login);
+ core.setOutput('approved_by', context.actor);
+
// Check if confirmation comment already exists
const comments = await github.rest.issues.listComments({
issue_number: prNumber,
@@ -156,3 +167,53 @@ jobs:
} catch (error) {
throw error;
}
+
+ - name: Record manual CLA approval
+ if: steps.process-cla-approval.outputs.pr_number
+ run: |
+ # Ensure signatures file exists
+ if [ ! -f "cla-signatures.json" ]; then
+ echo '{"signatures": []}' > cla-signatures.json
+ fi
+
+ # Extract approval details from previous step outputs
+ USERNAME="${{ steps.process-cla-approval.outputs.pr_author }}"
+ DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
+ PR_NUMBER="${{ steps.process-cla-approval.outputs.pr_number }}"
+ APPROVED_BY="${{ steps.process-cla-approval.outputs.approved_by }}"
+
+ echo "Recording manual CLA approval:"
+ echo " Username: $USERNAME"
+ echo " PR Number: $PR_NUMBER"
+ echo " Approved by: $APPROVED_BY"
+ echo " Date: $DATE"
+
+ # Check if this user already has a signature for this PR
+ EXISTING_SIGNATURE=$(jq --arg user "$USERNAME" --arg pr "$PR_NUMBER" '.signatures[] | select(.username == $user and .pr_number == ($pr | tonumber))' cla-signatures.json)
+
+ if [ -z "$EXISTING_SIGNATURE" ]; then
+ # Add new signature entry
+ jq --arg user "$USERNAME" \
+ --arg date "$DATE" \
+ --arg pr "$PR_NUMBER" \
+ --arg approved_by "$APPROVED_BY" \
+ '.signatures += [{
+ "username": $user,
+ "date": $date,
+ "pr_number": ($pr | tonumber),
+ "approved_by": $approved_by
+ }]' cla-signatures.json > tmp.json && mv tmp.json cla-signatures.json
+
+ echo "New CLA approval signature added"
+ else
+ echo "Signature already exists for this user and PR"
+ fi
+
+ # Commit the updated file
+ git config user.name "github-actions[bot]"
+ git config user.email "github-actions[bot]@users.noreply.github.com"
+ git add cla-signatures.json
+ git commit -m "Add manual CLA approval for @$USERNAME (PR #$PR_NUMBER) by @$APPROVED_BY" || echo "No changes to commit"
+ git push
+
+ echo "Manual CLA approval recorded successfully"
diff --git a/.github/workflows/trademark-cla-notice.yml b/.github/workflows/trademark-cla-notice.yml
index 2bd604f1fa6..0f85671c6c5 100644
--- a/.github/workflows/trademark-cla-notice.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -146,72 +146,75 @@ jobs:
);
if (!existingClaComment && context.eventName === 'pull_request') {
- const claText = `# CLA Agreement Required - MERGE BLOCKED
-
- # Trademark License Addendum
-
-
- Click to see Trademark License Addendum
-
- This Trademark License Addendum ("Addendum") shall, if You have opted
- in by replying to the comment that references this Addendum that you
- have read and agree to theContributor License Agreement Addendum,
- supplement the terms of the Individual Contributor License Agreement
- between You and the Company ("Agreement"). Capitalized terms not
- defined herein shall have the meanings ascribed to them in the
- Agreement.
-
- 1. Grant of Trademark License. Subject to the terms and conditions
- of this Addendum, You grant to the Company a revocable, worldwide,
- non-exclusive, non-sublicensable (except for contractors or agents
- acting on the Company's behalf, for whose compliance with this
- Addendum Company agrees to be responsible), royalty-free, and non-transferable
- right to display the Partner Trademarks, solely for the purpose of
- marketing and promoting your Contribution (i) on the Company's website
- and in any Company in-product integrations page; and (ii) in
- marketing, sales, and product materials for Company products.
- "Partner Trademarks" mean Your employer's name and any employer
- brand features (e.g., logo) you submit to the Company in connection with your
- Contribution.
- 2. Legal authority. You represent that you are legally entitled to
- grant the above license. If your employer(s) has rights to
- intellectual property in the Partner Trademarks, you represent that
- you have received permission to grant the above license on behalf
- of that employer, or that your employer has executed a separate
- agreement with the Company concerning the subject matter of this
- Addendum.
- 3. Conditions. The license in Section 1 is subject to the following
- conditions:
- i. The Company shall use the Partner Trademarks in accordance with
- any reasonable trademark usage guidelines You provide;
- ii. You may revoke this license at any time upon thirty (30) days'
- written notice to the Company, after which the Company shall use
- commercially reasonable efforts to cease all further public
- use of the Partner Trademarks (but may maintain uses in archived
- web pages, changelogs, and previously distributed materials).
- iii. The Company acknowledges and agrees that it does not own the
- Partner Trademarks and that all goodwill derived from the use
- of the Partner Trademarks inures solely to benefit of the
- Partner Trademarks' owner(s).
- iv. The Company shall use the Partner Trademarks in a professional
- manner consistent with industry standards and shall not use
- them in any way that would reasonably be expected to diminish
- their value or harm the reputation of the Partner Trademarks'
- owner(s). The Company's use of Partner Trademarks shall not
- imply endorsement, sponsorship, or affiliation beyond the
- existence of the Contribution in the Company's integration program.
- v. The Company will not use the Partner Trademarks in connection
- with search engine rankings, ad word purchases, or as part of a
- trade name, business name, or Internet domain name.
-
-
-
- **To unblock this PR, reply with exactly:**
-
- \`\`\`
- I have read and agree to the Contributor License Agreement Addendum.
- CLA-SIGNATURE: ${prAuthor}
- \`\`\``;
+ const claText = `
+# Trademark License Addendum
+
+Merging of this pull request is temporarily blocked. Please
+read and agree to the Trademark License Addendum below to
+unblock merging of this pull request.
+
+
+Click to see Trademark License Addendum
+
+This Trademark License Addendum ("Addendum") shall, if You have opted
+in by replying to the comment that references this Addendum that you
+have read and agree to theContributor License Agreement Addendum,
+supplement the terms of the Individual Contributor License Agreement
+between You and the Company ("Agreement"). Capitalized terms not
+defined herein shall have the meanings ascribed to them in the
+Agreement.
+
+1. Grant of Trademark License. Subject to the terms and conditions
+of this Addendum, You grant to the Company a revocable, worldwide,
+non-exclusive, non-sublicensable (except for contractors or agents
+acting on the Company's behalf, for whose compliance with this
+Addendum Company agrees to be responsible), royalty-free, and non-transferable
+right to display the Partner Trademarks, solely for the purpose of
+marketing and promoting your Contribution (i) on the Company's website
+and in any Company in-product integrations page; and (ii) in marketing, sales,
+and product materials for Company products. “Partner Trademarks” mean Your
+employer’s name and any employer brand features (e.g., logo) You submit now or
+in the future to the Company in connection with your Contributions.
+2. Legal authority. You represent that you are legally entitled to
+grant the above license. If your employer(s) has rights to
+intellectual property in the Partner Trademarks, you represent that
+you have received permission to grant the above license on behalf
+of that employer, or that your employer has executed a separate
+agreement with the Company concerning the subject matter of this
+Addendum.
+3. Conditions. The license in Section 1 is subject to the following
+conditions:
+i. The Company shall use the Partner Trademarks in accordance with
+ any reasonable trademark usage guidelines You provide;
+ii. You may revoke this license at any time upon thirty (30) days'
+ written notice to the Company, after which the Company shall use
+ commercially reasonable efforts to cease all further public
+ use of the Partner Trademarks (but may maintain uses in archived
+ web pages, changelogs, and previously distributed materials).
+iii. The Company acknowledges and agrees that it does not own the
+ Partner Trademarks and that all goodwill derived from the use
+ of the Partner Trademarks inures solely to benefit of the
+ Partner Trademarks' owner(s).
+iv. The Company shall use the Partner Trademarks in a professional
+ manner consistent with industry standards and shall not use
+ them in any way that would reasonably be expected to diminish
+ their value or harm the reputation of the Partner Trademarks'
+ owner(s). The Company's use of Partner Trademarks shall not
+ imply endorsement, sponsorship, or affiliation beyond the
+ existence of the Contribution in the Company's integration program.
+v. The Company will not use the Partner Trademarks in connection
+ with search engine rankings, ad word purchases, or as part of a
+ trade name, business name, or Internet domain name.
+
+
+
+**To unblock this PR, reply with exactly:**
+
+\`\`\`
+I agree to the Trademark License Addendum
+CLA-SIGNATURE: ${prAuthor}
+\`\`\`
+ `;
await github.rest.issues.createComment({
issue_number: prNumber,
From 264f41680a9bda224818d8578252cd096116b4c1 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 06:36:23 +0200
Subject: [PATCH 10/17] fix workflow
---
.github/workflows/trademark-cla-notice.yml | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/trademark-cla-notice.yml b/.github/workflows/trademark-cla-notice.yml
index 0f85671c6c5..63aa18237c2 100644
--- a/.github/workflows/trademark-cla-notice.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -146,8 +146,7 @@ jobs:
);
if (!existingClaComment && context.eventName === 'pull_request') {
- const claText = `
-# Trademark License Addendum
+ const claText = `# Trademark License Addendum
Merging of this pull request is temporarily blocked. Please
read and agree to the Trademark License Addendum below to
@@ -213,9 +212,8 @@ v. The Company will not use the Partner Trademarks in connection
\`\`\`
I agree to the Trademark License Addendum
CLA-SIGNATURE: ${prAuthor}
-\`\`\`
- `;
-
+\`\`\``;
+
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
From 54678ba2d75ef7c8f99a0f4bb3095505f96e7e09 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 06:42:11 +0200
Subject: [PATCH 11/17] fix workflow error caused by string literals
---
.github/workflows/trademark-cla-notice.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/trademark-cla-notice.yml b/.github/workflows/trademark-cla-notice.yml
index 63aa18237c2..92862636932 100644
--- a/.github/workflows/trademark-cla-notice.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -209,10 +209,10 @@ v. The Company will not use the Partner Trademarks in connection
**To unblock this PR, reply with exactly:**
-\`\`\`
+\\\`\\\`\\\`
I agree to the Trademark License Addendum
CLA-SIGNATURE: ${prAuthor}
-\`\`\``;
+\\\`\\\`\\\``;
await github.rest.issues.createComment({
issue_number: prNumber,
From c38a2ffc18be3050e64cdfebe8b71b4986a0d23d Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 06:54:34 +0200
Subject: [PATCH 12/17] concatenate strings
---
.github/workflows/trademark-cla-notice.yml | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/trademark-cla-notice.yml b/.github/workflows/trademark-cla-notice.yml
index 92862636932..bc39ab5f6c0 100644
--- a/.github/workflows/trademark-cla-notice.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -146,7 +146,7 @@ jobs:
);
if (!existingClaComment && context.eventName === 'pull_request') {
- const claText = `# Trademark License Addendum
+ const claText = '# Trademark License Addendum
Merging of this pull request is temporarily blocked. Please
read and agree to the Trademark License Addendum below to
@@ -207,12 +207,10 @@ v. The Company will not use the Partner Trademarks in connection
-**To unblock this PR, reply with exactly:**
-
-\\\`\\\`\\\`
+**To unblock this PR, reply with exactly:**' + ````
I agree to the Trademark License Addendum
CLA-SIGNATURE: ${prAuthor}
-\\\`\\\`\\\``;
+````;
await github.rest.issues.createComment({
issue_number: prNumber,
From 35331cad6a2243ced3ab975fbaa6af4a8911defb Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 07:05:51 +0200
Subject: [PATCH 13/17] testing git workflows is a nightmare
---
.github/workflows/trademark-cla-notice.yml | 125 ++++++++++-----------
1 file changed, 60 insertions(+), 65 deletions(-)
diff --git a/.github/workflows/trademark-cla-notice.yml b/.github/workflows/trademark-cla-notice.yml
index bc39ab5f6c0..1ff579b5267 100644
--- a/.github/workflows/trademark-cla-notice.yml
+++ b/.github/workflows/trademark-cla-notice.yml
@@ -146,71 +146,66 @@ jobs:
);
if (!existingClaComment && context.eventName === 'pull_request') {
- const claText = '# Trademark License Addendum
-
-Merging of this pull request is temporarily blocked. Please
-read and agree to the Trademark License Addendum below to
-unblock merging of this pull request.
-
-
-Click to see Trademark License Addendum
-
-This Trademark License Addendum ("Addendum") shall, if You have opted
-in by replying to the comment that references this Addendum that you
-have read and agree to theContributor License Agreement Addendum,
-supplement the terms of the Individual Contributor License Agreement
-between You and the Company ("Agreement"). Capitalized terms not
-defined herein shall have the meanings ascribed to them in the
-Agreement.
-
-1. Grant of Trademark License. Subject to the terms and conditions
-of this Addendum, You grant to the Company a revocable, worldwide,
-non-exclusive, non-sublicensable (except for contractors or agents
-acting on the Company's behalf, for whose compliance with this
-Addendum Company agrees to be responsible), royalty-free, and non-transferable
-right to display the Partner Trademarks, solely for the purpose of
-marketing and promoting your Contribution (i) on the Company's website
-and in any Company in-product integrations page; and (ii) in marketing, sales,
-and product materials for Company products. “Partner Trademarks” mean Your
-employer’s name and any employer brand features (e.g., logo) You submit now or
-in the future to the Company in connection with your Contributions.
-2. Legal authority. You represent that you are legally entitled to
-grant the above license. If your employer(s) has rights to
-intellectual property in the Partner Trademarks, you represent that
-you have received permission to grant the above license on behalf
-of that employer, or that your employer has executed a separate
-agreement with the Company concerning the subject matter of this
-Addendum.
-3. Conditions. The license in Section 1 is subject to the following
-conditions:
-i. The Company shall use the Partner Trademarks in accordance with
- any reasonable trademark usage guidelines You provide;
-ii. You may revoke this license at any time upon thirty (30) days'
- written notice to the Company, after which the Company shall use
- commercially reasonable efforts to cease all further public
- use of the Partner Trademarks (but may maintain uses in archived
- web pages, changelogs, and previously distributed materials).
-iii. The Company acknowledges and agrees that it does not own the
- Partner Trademarks and that all goodwill derived from the use
- of the Partner Trademarks inures solely to benefit of the
- Partner Trademarks' owner(s).
-iv. The Company shall use the Partner Trademarks in a professional
- manner consistent with industry standards and shall not use
- them in any way that would reasonably be expected to diminish
- their value or harm the reputation of the Partner Trademarks'
- owner(s). The Company's use of Partner Trademarks shall not
- imply endorsement, sponsorship, or affiliation beyond the
- existence of the Contribution in the Company's integration program.
-v. The Company will not use the Partner Trademarks in connection
- with search engine rankings, ad word purchases, or as part of a
- trade name, business name, or Internet domain name.
-
-
-
-**To unblock this PR, reply with exactly:**' + ````
-I agree to the Trademark License Addendum
-CLA-SIGNATURE: ${prAuthor}
-````;
+ const claText = '# Trademark License Addendum\n\n' +
+ 'Merging of this pull request is temporarily blocked. Please \n' +
+ 'read and agree to the Trademark License Addendum below to \n' +
+ 'unblock merging of this pull request.\n\n' +
+ '\n' +
+ 'Click to see Trademark License Addendum
\n\n' +
+ 'This Trademark License Addendum ("Addendum") shall, if You have opted \n' +
+ 'in by replying to the comment that references this Addendum that you\n' +
+ 'have read and agree to theContributor License Agreement Addendum,\n' +
+ 'supplement the terms of the Individual Contributor License Agreement\n' +
+ 'between You and the Company ("Agreement"). Capitalized terms not\n' +
+ 'defined herein shall have the meanings ascribed to them in the \n' +
+ 'Agreement.\n\n' +
+ '1. Grant of Trademark License. Subject to the terms and conditions \n' +
+ 'of this Addendum, You grant to the Company a revocable, worldwide,\n' +
+ 'non-exclusive, non-sublicensable (except for contractors or agents\n' +
+ 'acting on the Company\'s behalf, for whose compliance with this \n' +
+ 'Addendum Company agrees to be responsible), royalty-free, and non-transferable\n' +
+ 'right to display the Partner Trademarks, solely for the purpose of\n' +
+ 'marketing and promoting your Contribution (i) on the Company\'s website\n' +
+ 'and in any Company in-product integrations page; and (ii) in marketing, sales,\n' +
+ 'and product materials for Company products. "Partner Trademarks" mean Your \n' +
+ 'employer\'s name and any employer brand features (e.g., logo) You submit now or \n' +
+ 'in the future to the Company in connection with your Contributions.\n' +
+ '2. Legal authority. You represent that you are legally entitled to\n' +
+ 'grant the above license. If your employer(s) has rights to \n' +
+ 'intellectual property in the Partner Trademarks, you represent that\n' +
+ 'you have received permission to grant the above license on behalf \n' +
+ 'of that employer, or that your employer has executed a separate \n' +
+ 'agreement with the Company concerning the subject matter of this \n' +
+ 'Addendum.\n' +
+ '3. Conditions. The license in Section 1 is subject to the following\n' +
+ 'conditions:\n' +
+ 'i. The Company shall use the Partner Trademarks in accordance with\n' +
+ ' any reasonable trademark usage guidelines You provide;\n' +
+ 'ii. You may revoke this license at any time upon thirty (30) days\'\n' +
+ ' written notice to the Company, after which the Company shall use\n' +
+ ' commercially reasonable efforts to cease all further public\n' +
+ ' use of the Partner Trademarks (but may maintain uses in archived\n' +
+ ' web pages, changelogs, and previously distributed materials).\n' +
+ 'iii. The Company acknowledges and agrees that it does not own the \n' +
+ ' Partner Trademarks and that all goodwill derived from the use \n' +
+ ' of the Partner Trademarks inures solely to benefit of the \n' +
+ ' Partner Trademarks\' owner(s).\n' +
+ 'iv. The Company shall use the Partner Trademarks in a professional\n' +
+ ' manner consistent with industry standards and shall not use \n' +
+ ' them in any way that would reasonably be expected to diminish \n' +
+ ' their value or harm the reputation of the Partner Trademarks\' \n' +
+ ' owner(s). The Company\'s use of Partner Trademarks shall not \n' +
+ ' imply endorsement, sponsorship, or affiliation beyond the \n' +
+ ' existence of the Contribution in the Company\'s integration program.\n' +
+ 'v. The Company will not use the Partner Trademarks in connection \n' +
+ ' with search engine rankings, ad word purchases, or as part of a\n' +
+ ' trade name, business name, or Internet domain name.\n\n' +
+ ' \n\n' +
+ '**To unblock this PR, reply with exactly:**\n' +
+ '```\n' +
+ 'I agree to the Trademark License Addendum\n' +
+ 'CLA-SIGNATURE: ' + prAuthor + '\n' +
+ '```';
await github.rest.issues.createComment({
issue_number: prNumber,
From b5bc971b325ed4ff4001b0f38a5fcbb675ff52c0 Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 07:08:25 +0200
Subject: [PATCH 14/17] trigger flow for testing
From 3e0e01eaa3f8a81911f6d94dcff00d9c754d9a0d Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 07:11:44 +0200
Subject: [PATCH 15/17] remove test image
---
.../integrations/data-visualization/img.png | Bin 13758 -> 0 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 static/images/integrations/data-visualization/img.png
diff --git a/static/images/integrations/data-visualization/img.png b/static/images/integrations/data-visualization/img.png
deleted file mode 100644
index ce09ab872fb8f9a7820725a910b79f675c2d0b79..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 13758
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
Date: Sat, 19 Jul 2025 07:30:18 +0200
Subject: [PATCH 16/17] Delete
docs/integrations/data-visualization/made-up-integration-for-test.md
---
.../made-up-integration-for-test.md | 13 -------------
1 file changed, 13 deletions(-)
delete mode 100644 docs/integrations/data-visualization/made-up-integration-for-test.md
diff --git a/docs/integrations/data-visualization/made-up-integration-for-test.md b/docs/integrations/data-visualization/made-up-integration-for-test.md
deleted file mode 100644
index bc25a37fef1..00000000000
--- a/docs/integrations/data-visualization/made-up-integration-for-test.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-sidebar_label: 'ClickClick'
-slug: /integrations/clickclick
-keywords: ['clickhouse', 'ClickClick', 'connect', 'integrate', 'ui', 'embedded']
-description: 'ClickClick is a made up analytics platform with a native ClickHouse integration'
-title: 'Integrating ClickClick with ClickHouse'
-sidebar: 'integrations'
----
-
-import Image from '@theme/IdealImage';
-import some_image from '@site/static/images/integrations/data-visualization/clickclick.png';
-
-
\ No newline at end of file
From d96194c006ac5f8677cb01051f6dad09c00d40fe Mon Sep 17 00:00:00 2001
From: Shaun Struwig <41984034+Blargian@users.noreply.github.com>
Date: Sat, 19 Jul 2025 07:36:36 +0200
Subject: [PATCH 17/17] Update sidebars.js
---
sidebars.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/sidebars.js b/sidebars.js
index 7c662e70d37..66230ab576c 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -901,7 +901,6 @@ const sidebars = {
"integrations/data-visualization/looker-and-clickhouse",
"integrations/data-visualization/looker-studio-and-clickhouse",
"integrations/data-visualization/luzmo-and-clickhouse",
- "integrations/data-visualization/made-up-integration-for-test",
"integrations/data-visualization/metabase-and-clickhouse",
"integrations/data-visualization/mitzu-and-clickhouse",
"integrations/data-visualization/omni-and-clickhouse",