Skip to content

Commit 3c0ee1b

Browse files
committed
Merge remote-tracking branch 'upstream/master'
2 parents f942698 + 6871d26 commit 3c0ee1b

439 files changed

Lines changed: 11078 additions & 633 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.
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
name: PR Branch Check
2+
3+
on:
4+
# Using pull_request_target instead of pull_request for secure handling of fork PRs
5+
pull_request_target:
6+
# Only run on these PR events
7+
types: [opened, synchronize, reopened]
8+
# Only check PRs targeting these branches
9+
branches:
10+
- main
11+
- master
12+
13+
permissions:
14+
pull-requests: write
15+
issues: write
16+
17+
jobs:
18+
check-branch:
19+
runs-on: ubuntu-slim
20+
steps:
21+
- name: Check and Comment on PR
22+
# Only process fork PRs with specific branch conditions
23+
# Must be a fork AND (source is main/master OR target is main/master)
24+
if: |
25+
github.event.pull_request.head.repo.fork == true &&
26+
((github.event.pull_request.head.ref == 'main' || github.event.pull_request.head.ref == 'master') ||
27+
(github.event.pull_request.base.ref == 'main' || github.event.pull_request.base.ref == 'master'))
28+
uses: actions/github-script@v9
29+
with:
30+
github-token: ${{ secrets.GITHUB_TOKEN }}
31+
script: |
32+
let message = '';
33+
34+
// Check if the fork has open PRs (indicates pull bot or similar is active)
35+
const forkOwner = context.payload.pull_request.head.repo.owner.login;
36+
const forkRepo = context.payload.pull_request.head.repo.name;
37+
const forkPullsUrl = context.payload.pull_request.head.repo.html_url + '/pulls';
38+
39+
let openPRs = [];
40+
try {
41+
const { data: prs } = await github.rest.pulls.list({
42+
owner: forkOwner,
43+
repo: forkRepo,
44+
state: 'open',
45+
per_page: 5
46+
});
47+
openPRs = prs;
48+
} catch (e) {
49+
// Can't read fork PRs — skip
50+
}
51+
52+
message += '🔄 If you are attempting to update your CIPP-API repo please follow the instructions at: https://docs.cipp.app/setup/self-hosting-guide/updating. Are you a sponsor? Contact the helpdesk for direct assistance with updating to the latest version.';
53+
54+
if (openPRs.length > 0) {
55+
message += ` It looks like you may already have a pending update PR on your fork — check your [open pull requests](${forkPullsUrl}) to accept it.`;
56+
} else {
57+
message += ` You can enable [Pull Bot](https://github.com/apps/pull) or [Repo Sync](https://github.com/apps/repo-sync) to automatically keep your fork up to date.`;
58+
}
59+
message += '\n\n';
60+
61+
// Check if PR is targeting main/master
62+
if (context.payload.pull_request.base.ref === 'main' || context.payload.pull_request.base.ref === 'master') {
63+
message += '⚠️ PRs cannot target the main branch directly. If you are attempting to contribute code please PR to the dev branch.\n\n';
64+
}
65+
66+
// Check if PR is from a fork's main/master branch
67+
if (context.payload.pull_request.head.repo.fork &&
68+
(context.payload.pull_request.head.ref === 'main' || context.payload.pull_request.head.ref === 'master')) {
69+
message += '⚠️ This PR cannot be merged because it originates from your fork\'s main/master branch. If you are attempting to contribute code please PR from your dev branch or another non-main/master branch.\n\n';
70+
}
71+
72+
message += '🔒 This PR will now be automatically closed due to the above rules.';
73+
74+
// Post the comment
75+
await github.rest.issues.createComment({
76+
...context.repo,
77+
issue_number: context.issue.number,
78+
body: message
79+
});
80+
81+
// Close the PR
82+
await github.rest.pulls.update({
83+
...context.repo,
84+
pull_number: context.issue.number,
85+
state: 'closed'
86+
});

Config/CIPPTimers.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
"Cron": "0 0 */12 * * *",
7979
"Priority": 4,
8080
"RunOnProcessor": true,
81+
"TZOffset": true,
8182
"PreferredProcessor": "standards"
8283
},
8384
{
@@ -87,6 +88,7 @@
8788
"Cron": "0 15 */12 * * *",
8889
"Priority": 5,
8990
"RunOnProcessor": true,
91+
"TZOffset": true,
9092
"PreferredProcessor": "standards"
9193
},
9294
{
@@ -120,6 +122,7 @@
120122
"Cron": "0 0 0 * * 0",
121123
"Priority": 7,
122124
"RunOnProcessor": true,
125+
"TZOffset": true,
123126
"IsSystem": true
124127
},
125128
{
@@ -137,6 +140,7 @@
137140
"Description": "Orchestrator to process domains",
138141
"Cron": "0 30 5 * * *",
139142
"Priority": 22,
143+
"TZOffset": true,
140144
"RunOnProcessor": true
141145
},
142146
{
@@ -149,6 +153,7 @@
149153
"Cron": "0 0 23 * * *",
150154
"Priority": 10,
151155
"RunOnProcessor": true,
156+
"TZOffset": true,
152157
"IsSystem": true
153158
},
154159
{
@@ -158,6 +163,7 @@
158163
"Cron": "0 0 0 * * *",
159164
"Priority": 10,
160165
"RunOnProcessor": true,
166+
"TZOffset": true,
161167
"IsSystem": true
162168
},
163169
{
@@ -166,6 +172,7 @@
166172
"Description": "Timer to process billing",
167173
"Cron": "0 0 0 * * *",
168174
"Priority": 12,
175+
"TZOffset": true,
169176
"RunOnProcessor": true
170177
},
171178
{
@@ -174,6 +181,7 @@
174181
"Description": "Orchestrator to process BPA reports",
175182
"Cron": "0 0 3 * * *",
176183
"Priority": 10,
184+
"TZOffset": true,
177185
"RunOnProcessor": true
178186
},
179187
{
@@ -191,6 +199,7 @@
191199
"Cron": "0 0 0 * * *",
192200
"Priority": 15,
193201
"RunOnProcessor": true,
202+
"TZOffset": true,
194203
"IsSystem": true
195204
},
196205
{
@@ -200,6 +209,7 @@
200209
"Cron": "0 0 23 * * *",
201210
"Priority": 20,
202211
"RunOnProcessor": true,
212+
"TZOffset": true,
203213
"IsSystem": true
204214
},
205215
{
@@ -212,6 +222,7 @@
212222
"Cron": "0 0 0 * * *",
213223
"Priority": 20,
214224
"RunOnProcessor": true,
225+
"TZOffset": true,
215226
"IsSystem": true
216227
},
217228
{
@@ -221,6 +232,7 @@
221232
"Cron": "0 0 2 * * *",
222233
"Priority": 21,
223234
"RunOnProcessor": true,
235+
"TZOffset": true,
224236
"IsSystem": true
225237
},
226238
{
@@ -230,6 +242,7 @@
230242
"Cron": "0 30 2 * * *",
231243
"Priority": 22,
232244
"RunOnProcessor": true,
245+
"TZOffset": true,
233246
"IsSystem": true
234247
},
235248
{
@@ -239,6 +252,7 @@
239252
"Cron": "0 0 3 * * *",
240253
"Priority": 23,
241254
"RunOnProcessor": true,
255+
"TZOffset": true,
242256
"IsSystem": true
243257
},
244258
{
@@ -248,6 +262,7 @@
248262
"Cron": "0 0 4 * * *",
249263
"Priority": 24,
250264
"RunOnProcessor": true,
265+
"TZOffset": true,
251266
"IsSystem": true
252267
}
253268
]

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/Domain Analyser/Push-DomainAnalyserDomain.ps1

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ function Push-DomainAnalyserDomain {
6262
MSCNAMEDKIMSelectors = ''
6363
EnterpriseEnrollment = ''
6464
EnterpriseRegistration = ''
65+
AutoDiscover = ''
6566
Score = ''
6667
MaximumScore = 160
6768
ScorePercentage = ''
@@ -293,6 +294,26 @@ function Push-DomainAnalyserDomain {
293294
}
294295
#EndRegion Intune Enrollment CNAME Check
295296

297+
#Region AutoDiscover Check
298+
try {
299+
$AutoDiscoverRecord = Read-AutoDiscoverRecord -Domain $Domain
300+
$AutoDiscoverFailCount = $AutoDiscoverRecord.ValidationFails | Measure-Object | Select-Object -ExpandProperty Count
301+
$AutoDiscoverWarnCount = $AutoDiscoverRecord.ValidationWarns | Measure-Object | Select-Object -ExpandProperty Count
302+
if ($AutoDiscoverFailCount -eq 0 -and $AutoDiscoverWarnCount -eq 0) {
303+
$Result.AutoDiscover = 'Correct'
304+
} elseif ($AutoDiscoverFailCount -eq 0) {
305+
$Result.AutoDiscover = "$($AutoDiscoverRecord.RecordType): $($AutoDiscoverRecord.Record)"
306+
$ScoreExplanation.Add("AutoDiscover $($AutoDiscoverRecord.RecordType) record points to unexpected target") | Out-Null
307+
} else {
308+
$Result.AutoDiscover = 'No Record'
309+
$ScoreExplanation.Add('No AutoDiscover DNS record found') | Out-Null
310+
}
311+
} catch {
312+
$Result.AutoDiscover = 'Error'
313+
Write-LogMessage -API 'DomainAnalyser' -tenant $DomainObject.TenantId -message "AutoDiscover check error for $Domain" -LogData (Get-CippException -Exception $_) -sev Error
314+
}
315+
#EndRegion AutoDiscover Check
316+
296317
#Region MSCNAME DKIM Records
297318
# Get Microsoft DKIM CNAME selector Records
298319
# Ugly, but i needed to create a scope/loop i could break out of without breaking the rest of the function

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/Graph Requests/Push-ListGraphRequestQueue.ps1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ function Push-ListGraphRequestQueue {
6363
Data = [string]$Json
6464
}
6565
Add-CIPPAzDataTableEntity @Table -Entity $GraphResults -Force | Out-Null
66+
67+
if ($env:CIPPNG -eq 'true') {
68+
try {
69+
[Craft.Services.CacheBridge]::InvalidateByScope('AllTenants')
70+
} catch {
71+
Write-Information "CacheBridge invalidation skipped: $($_.Exception.Message)"
72+
}
73+
}
74+
6675
return $true
6776
} catch {
6877
Write-Warning "Queue Error: $($_.Exception.Message)"

Modules/CIPPActivityTriggers/Public/Entrypoints/Activity Triggers/Push-CIPPDBCacheData.ps1

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,23 @@ function Push-CIPPDBCacheData {
6565
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Compliance license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
6666
}
6767

68-
Write-Information "License capabilities for $TenantFilter - Intune: $IntuneCapable, CA: $ConditionalAccessCapable, P2: $AzureADPremiumP2Capable, Exchange: $ExchangeCapable, Compliance: $ComplianceCapable"
68+
$SharePointCapable = $false
69+
try {
70+
$SharePointCapable = Test-CIPPStandardLicense -StandardName 'SharePointLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('SHAREPOINTWAC', 'SHAREPOINTSTANDARD', 'SHAREPOINTENTERPRISE', 'SHAREPOINTENTERPRISE_EDU', 'ONEDRIVE_BASIC', 'ONEDRIVE_ENTERPRISE') -SkipLog
71+
} catch {
72+
$ErrorMessage = Get-CippException -Exception $_
73+
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "SharePoint license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
74+
}
75+
76+
$TeamsCapable = $false
77+
try {
78+
$TeamsCapable = Test-CIPPStandardLicense -StandardName 'TeamsLicenseCheck' -TenantFilter $TenantFilter -RequiredCapabilities @('MCOSTANDARD', 'MCOEV', 'MCOIMP', 'TEAMS1', 'Teams_Room_Standard') -SkipLog
79+
} catch {
80+
$ErrorMessage = Get-CippException -Exception $_
81+
Write-LogMessage -API 'CIPPDBCache' -tenant $TenantFilter -message "Teams license check failed: $($_.Exception.Message)" -sev Warning -LogData $ErrorMessage
82+
}
83+
84+
Write-Information "License capabilities for $TenantFilter - Intune: $IntuneCapable, CA: $ConditionalAccessCapable, P2: $AzureADPremiumP2Capable, Exchange: $ExchangeCapable, Compliance: $ComplianceCapable, SharePoint: $SharePointCapable, Teams: $TeamsCapable"
6985

7086
# Build grouped collection tasks — one activity per license category instead of one per cache type
7187
$Tasks = [System.Collections.Generic.List[object]]::new()
@@ -174,6 +190,30 @@ function Push-CIPPDBCacheData {
174190
Write-Host "Skipping Compliance data collection for $TenantFilter - no required license"
175191
}
176192

193+
if ($SharePointCapable) {
194+
$Tasks.Add(@{
195+
FunctionName = 'ExecCIPPDBCache'
196+
CollectionType = 'SharePoint'
197+
TenantFilter = $TenantFilter
198+
QueueId = $QueueId
199+
QueueName = "DB Cache SharePoint - $TenantFilter"
200+
})
201+
} else {
202+
Write-Host "Skipping SharePoint data collection for $TenantFilter - no required license"
203+
}
204+
205+
if ($TeamsCapable) {
206+
$Tasks.Add(@{
207+
FunctionName = 'ExecCIPPDBCache'
208+
CollectionType = 'Teams'
209+
TenantFilter = $TenantFilter
210+
QueueId = $QueueId
211+
QueueName = "DB Cache Teams - $TenantFilter"
212+
})
213+
} else {
214+
Write-Host "Skipping Teams data collection for $TenantFilter - no required license"
215+
}
216+
177217
Write-Information "Built $($Tasks.Count) grouped cache tasks for tenant $TenantFilter (down from individual per-type tasks)"
178218

179219
# Return the task list — the PostExecution function will aggregate and start a flat orchestrator

0 commit comments

Comments
 (0)