Skip to content

Commit db4e1d0

Browse files
authored
Merge pull request #15 from nextcloud/ci/noid/add-ci
Add ci
2 parents 23e3efb + 9b112e0 commit db4e1d0

131 files changed

Lines changed: 22565 additions & 14353 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
2+
# SPDX-License-Identifier: CC0-1.0
3+
version: 2
4+
updates:
5+
- package-ecosystem: composer
6+
directories:
7+
- "/"
8+
- "/vendor-bin/csfixer"
9+
- "/vendor-bin/openapi-extractor"
10+
- "/vendor-bin/phpunit"
11+
- "/vendor-bin/psalm"
12+
schedule:
13+
interval: weekly
14+
day: saturday
15+
time: "03:00"
16+
timezone: Europe/Paris
17+
cooldown:
18+
default-days: 10
19+
commit-message:
20+
prefix: "build"
21+
include: "scope"
22+
versioning-strategy: "increase"
23+
labels:
24+
- 3. to review
25+
- dependencies
26+
- package-ecosystem: npm
27+
directory: "/"
28+
schedule:
29+
interval: weekly
30+
day: saturday
31+
time: "03:00"
32+
timezone: Europe/Paris
33+
cooldown:
34+
default-days: 10
35+
commit-message:
36+
prefix: "build"
37+
include: "scope"
38+
versioning-strategy: "increase"
39+
open-pull-requests-limit: 10
40+
labels:
41+
- 3. to review
42+
- dependencies

.github/workflows/ai-policy.yml

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
# This workflow is provided via the organization template repository
2+
#
3+
# https://github.com/nextcloud/.github
4+
# https://docs.github.com/en/actions/learn-github-actions/sharing-workflows-with-your-organization
5+
#
6+
# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
7+
# SPDX-License-Identifier: MIT
8+
9+
name: AI Policy
10+
11+
on:
12+
pull_request:
13+
types: [opened, synchronize, reopened]
14+
branches: [master, main]
15+
16+
permissions:
17+
contents: read
18+
# Required to add the "AI assisted" label via `gh pr edit --add-label`
19+
pull-requests: write
20+
# Required to create the "AI assisted" label via the REST labels endpoint
21+
# (labels are an issues-scoped resource in the GitHub API)
22+
issues: write
23+
24+
concurrency:
25+
group: ai-policy-${{ github.head_ref || github.run_id }}
26+
cancel-in-progress: true
27+
28+
jobs:
29+
check-ai-trailers:
30+
runs-on: ubuntu-latest-low
31+
steps:
32+
- name: Collect PR commit messages
33+
id: collect
34+
env:
35+
# Fall back to the default token when the PAT is unavailable
36+
# (e.g. Dependabot- or fork-triggered runs don't receive Actions secrets)
37+
GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT || github.token }}
38+
COMMITS_URL: ${{ github.event.pull_request.commits_url }}
39+
run: |
40+
set -euo pipefail
41+
gh api ${COMMITS_URL} | jq -r '.[] | .commit.message' > /tmp/pr_commits.txt
42+
echo "--- PR commit messages ---"
43+
cat /tmp/pr_commits.txt
44+
echo "--------------------------"
45+
46+
- name: Define shared agent detection patterns
47+
run: |
48+
set -euo pipefail
49+
50+
# Email addresses known to be used by coding agents.
51+
# These should never appear in Signed-off-by because the DCO can only be attested by a human.
52+
EMAIL_PATTERN="copilot@github\.com\
53+
|noreply@anthropic\.com\
54+
|devin@cognition\.ai\
55+
|devin@cognition-labs\.com\
56+
|aider@aider\.chat\
57+
|noreply@aider\.chat\
58+
|codex@openai\.com\
59+
|cursor@anysphere\.com\
60+
|windsurf@codeium\.com\
61+
|codeium@codeium\.com\
62+
|amazon-q@amazon\.com\
63+
|codewhisperer@amazon\.com\
64+
|gemini-code-assist@google\.com\
65+
|openhands@all-hands\.dev\
66+
|swe-agent@princeton\.edu"
67+
68+
# Strip embedded whitespace (used above only for readability)
69+
EMAIL_PATTERN=$(echo "$EMAIL_PATTERN" | tr -d ' \n')
70+
echo "AGENT_EMAIL_PATTERN=${EMAIL_PATTERN}" >> "$GITHUB_ENV"
71+
72+
# Display-name prefixes used by known coding agents (shared by Signed-off-by and Co-Authored-By checks)
73+
# shellcheck disable=SC2016
74+
echo 'AGENT_NAMES=GitHub Copilot|Claude( [A-Za-z0-9. -]+)?|Devin( AI)?|aider( \(.*\))?|OpenAI Codex|Cursor( AI)?|Windsurf|Amazon Q|CodeWhisperer|Gemini Code Assist|OpenHands|SWE-agent|AutoCodeRover|Tabnine' >> "$GITHUB_ENV"
75+
76+
- name: Check for AI-assistant / Assisted-by trailers
77+
id: ai_trailers
78+
run: |
79+
set -euo pipefail
80+
AI_ASSISTED=false
81+
if grep -qiE '^(AI-assistant|Assisted-by|AI-Assisted-By):' /tmp/pr_commits.txt; then
82+
AI_ASSISTED=true
83+
echo "Found AI-assistant/Assisted-by/AI-Assisted-By trailer(s):"
84+
grep -iE '^(AI-assistant|Assisted-by|AI-Assisted-By):' /tmp/pr_commits.txt
85+
fi
86+
echo "ai_assisted=${AI_ASSISTED}" >> "$GITHUB_OUTPUT"
87+
88+
- name: Check for coding-agent Signed-off-by trailers
89+
id: agent_signoff
90+
run: |
91+
set -euo pipefail
92+
93+
EMAIL_HITS=$(grep -iE "^Signed-off-by:.*<(${AGENT_EMAIL_PATTERN})>" /tmp/pr_commits.txt 2>/dev/null || true)
94+
NAME_HITS=$(grep -iE "^Signed-off-by: *(${AGENT_NAMES}) *[<(]" /tmp/pr_commits.txt 2>/dev/null || true)
95+
96+
AGENT_LINES=$(printf '%s\n%s' "$EMAIL_HITS" "$NAME_HITS" | sort -u | sed '/^[[:space:]]*$/d')
97+
98+
AGENT_SIGNOFF=false
99+
if [ -n "$AGENT_LINES" ]; then
100+
AGENT_SIGNOFF=true
101+
fi
102+
103+
echo "agent_signoff=${AGENT_SIGNOFF}" >> "$GITHUB_OUTPUT"
104+
{
105+
echo "agent_lines<<AGENT_EOF"
106+
echo "${AGENT_LINES}"
107+
echo "AGENT_EOF"
108+
} >> "$GITHUB_OUTPUT"
109+
110+
- name: Check for coding-agent Co-Authored-By trailers
111+
id: co_authored
112+
run: |
113+
set -euo pipefail
114+
115+
EMAIL_HITS=$(grep -iE "^Co-Authored-By:.*<(${AGENT_EMAIL_PATTERN})>" /tmp/pr_commits.txt 2>/dev/null || true)
116+
NAME_HITS=$(grep -iE "^Co-Authored-By: *(${AGENT_NAMES}) *[<(]" /tmp/pr_commits.txt 2>/dev/null || true)
117+
118+
CO_AUTHORED=false
119+
if [ -n "$EMAIL_HITS" ] || [ -n "$NAME_HITS" ]; then
120+
CO_AUTHORED=true
121+
echo "Found coding-agent Co-Authored-By trailer(s):"
122+
printf '%s\n%s' "$EMAIL_HITS" "$NAME_HITS" | sort -u | sed '/^[[:space:]]*$/d'
123+
fi
124+
125+
echo "co_authored=${CO_AUTHORED}" >> "$GITHUB_OUTPUT"
126+
127+
- name: Create 'AI assisted' label if absent
128+
if: steps.ai_trailers.outputs.ai_assisted == 'true' || steps.agent_signoff.outputs.agent_signoff == 'true' || steps.co_authored.outputs.co_authored == 'true'
129+
env:
130+
# Fall back to the default token when the PAT is unavailable
131+
# (e.g. Dependabot- or fork-triggered runs don't receive Actions secrets)
132+
GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT || github.token }}
133+
run: |
134+
gh api "repos/${{ github.repository }}/labels" \
135+
--method POST \
136+
-f name="AI assisted" \
137+
-f color="d93f0b" \
138+
-f description="This PR contains AI-assisted commits" \
139+
2>/dev/null || true
140+
141+
- name: Label PR as AI assisted
142+
if: steps.ai_trailers.outputs.ai_assisted == 'true' || steps.agent_signoff.outputs.agent_signoff == 'true' || steps.co_authored.outputs.co_authored == 'true'
143+
env:
144+
# Fall back to the default token when the PAT is unavailable
145+
# (e.g. Dependabot- or fork-triggered runs don't receive Actions secrets)
146+
GH_TOKEN: ${{ secrets.COMMAND_BOT_PAT || github.token }}
147+
run: |
148+
gh api "repos/${{ github.repository }}/issues/${{ github.event.pull_request.number }}/labels" \
149+
--method POST \
150+
-f "labels[]=AI assisted"
151+
echo "Added 'AI assisted' label to PR #${{ github.event.pull_request.number }}"
152+
153+
- name: Fail on coding-agent Signed-off-by
154+
if: steps.agent_signoff.outputs.agent_signoff == 'true'
155+
env:
156+
AGENT_LINES: ${{ steps.agent_signoff.outputs.agent_lines }}
157+
AGENTS_MD_URL: https://github.com/${{ github.repository }}/blob/${{ github.base_ref }}/AGENTS.md
158+
run: |
159+
echo "::error title=Coding-agent sign-off detected::A Signed-off-by trailer from a known coding agent was found in one or more commits."
160+
echo ""
161+
echo "Offending trailer(s):"
162+
echo "${AGENT_LINES}"
163+
echo ""
164+
echo "The 'Signed-off-by' trailer represents the Developer Certificate of Origin (DCO)"
165+
echo "and must only be attested by a human contributor."
166+
echo "Please amend the affected commit(s) to remove the coding-agent sign-off"
167+
echo "and replace it with an 'Assisted-by' trailer, for example:"
168+
echo ""
169+
echo " Assisted-by: Claude Code:claude-sonnet-4-6"
170+
echo ""
171+
echo "References:"
172+
echo " • AGENTS.md (this repository)"
173+
echo " ${AGENTS_MD_URL}"
174+
echo " • AI Contribution Policy"
175+
echo " https://github.com/nextcloud/.github/blob/master/AI_POLICY.md"
176+
echo " • Contribution Guidelines"
177+
echo " https://github.com/nextcloud/.github/blob/master/CONTRIBUTING.md"
178+
exit 1

0 commit comments

Comments
 (0)