Skip to content

Enable sitePermissions for internal iOS users #34795

Enable sitePermissions for internal iOS users

Enable sitePermissions for internal iOS users #34795

Workflow file for this run

# Auto Respond to PR Workflow
#
# This workflow automatically generates and posts diff comments showing changes to generated configuration files.
#
# ## Generated Diff Output Guide:
# - **X files changed**: Multiple files with identical changes (collapsed for readability)
# - **X files identical**: Files that are exactly the same between base and PR branches
# - **File headers**: Show `--- filename (and X other files)` when multiple files share the same diff
# - **File lists**: Individual files are listed under each collapsed section
# - **Sections**: `latest` (current config version, expanded) and `legacy` (older versions, collapsed)
#
# The diff script groups files by their actual changes to reduce noise and improve review efficiency.
name: Auto Respond to PR
on:
pull_request_review:
pull_request:
types:
- opened
- edited
- closed
- reopened
- synchronize
- review_requested
jobs:
# Dedicated job to sync Asana tasks when PR is closed (merged or abandoned)
# Closes tasks for both merged PRs and abandoned PRs to clean up dead tasks
# Runs independently of the main workflow
sync_asana_on_close:
if: github.event.action == 'closed'
runs-on: ubuntu-latest
steps:
- uses: duckduckgo/action-asana-sync@v11
with:
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
ASANA_WORKSPACE_ID: ${{ secrets.ASANA_WORKSPACE_ID }}
ASANA_PROJECT_ID: '1206780406371845'
GITHUB_PAT: ${{ secrets.GH_RO_PAT }}
USER_MAP: ${{ vars.USER_MAP }}
ASSIGN_PR_AUTHOR: 'true'
auto_respond:
if: github.event.action != 'closed' && github.event.pull_request.user.login != 'dependabot[bot]'
runs-on: ubuntu-latest
concurrency: auto-respond-${{ github.event.pull_request.number }}
steps:
- name: Check if holiday period
run: |
if [ "$(date -u +%Y%m%d)" -lt "20260105" ]; then
echo "::notice::Auto review bot disabled until Jan 5th 2026"
exit 1
fi
- name: Debounce delay
run: sleep 5
- name: Check repository permissions
uses: actions/github-script@v9
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const username = context.payload.pull_request.user.login;
try {
const repoPermission = await github.rest.repos.getCollaboratorPermissionLevel({
owner: context.repo.owner,
repo: context.repo.repo,
username: username
});
const permission = repoPermission.data.permission;
if (permission === 'write' || permission === 'admin') {
console.log(`✅ User authorized to use workflow`);
} else {
core.setFailed(`User does not have sufficient repository permissions to use this workflow`);
}
} catch (error) {
core.setFailed(`Unable to verify user permissions`);
}
- name: Checkout base branch
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.base.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
path: base
- name: Checkout PR branch
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.ref }}
repository: ${{ github.event.pull_request.head.repo.full_name }}
path: pr
fetch-depth: 0
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version-file: pr/.nvmrc
- name: Run build script on base branch
run: |
cd base
npm ci
node index.js
cd ..
- name: Run build script on PR branch
run: |
cd pr
git config --global user.email "dax@duck.com"
git config --global user.name "dax"
git rebase -X theirs origin/${{ github.event.pull_request.base.ref }}
npm ci
node index.js
cd ..
- name: Create diff of file outputs
run: node pr/.github/scripts/diff-directories.js base/generated pr/generated > diff_output.txt
- name: Create JSON approval analysis
run: node pr/.github/scripts/json-diff-directories.js base/generated pr/generated > approval_output.txt
- name: Check changed files
id: check_files
run: |
cd pr
# Get list of changed files
changed_files=$(git diff --name-only origin/${{ github.event.pull_request.base.ref }}...HEAD)
echo "Changed files:"
echo "$changed_files"
# Check if all changed files are JSON files in overrides/ or features/
valid_changes=true
while IFS= read -r file; do
if [[ ! "$file" =~ ^(overrides|features)/.+\.json$ ]]; then
echo "❌ Invalid file change detected: $file"
echo "Only JSON files in overrides/ and features/ directories are allowed for auto-approval"
valid_changes=false
fi
done <<< "$changed_files"
if [ "$valid_changes" = true ]; then
echo "✅ All changed files are valid JSON files in allowed directories"
echo "files_valid=true" >> $GITHUB_OUTPUT
else
echo "files_valid=false" >> $GITHUB_OUTPUT
fi
- name: Parse approval output
id: approval
run: |
if grep -q "AUTO-APPROVED" approval_output.txt; then
echo "approved=true" >> $GITHUB_OUTPUT
else
echo "approved=false" >> $GITHUB_OUTPUT
fi
- name: Find Previous Diff Comment
uses: peter-evans/find-comment@v4
id: find_diff_comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'github-actions[bot]' # posted with default GITHUB_TOKEN
body-includes: 'Generated file outputs'
direction: last
- name: Find Previous Approval Comment
uses: peter-evans/find-comment@v4
id: find_approval_comment
with:
issue-number: ${{ github.event.pull_request.number }}
comment-author: 'daxtheduck' # posted with PRIVACY_CONFIG_PAT to trigger issue_comment events
body-includes: 'JSON approval analysis'
direction: last
- name: Create Diff Comment Body
uses: actions/github-script@v9
id: create_diff_body
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const diffOutput = fs.readFileSync('diff_output.txt', 'utf8');
let commentBody = `
### [Generated file outputs](https://github.com/duckduckgo/privacy-configuration/blob/main/.github/workflows/auto-respond-pr.yml#L5-L12):
*Time updated:* ${new Date().toUTCString()}
${diffOutput}
`
if (commentBody.length > 65536) {
commentBody = '❌ Generated diff output is too large to post as a comment, run locally to see the diff and validate'
}
core.setOutput('comment_body', commentBody);
- name: Check for existing approved reviews
uses: actions/github-script@v9
id: check_reviews
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { data: reviews } = await github.rest.pulls.listReviews({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
});
const hasApprovedReview = reviews.some(review =>
review.state === 'APPROVED' &&
review.user.login === 'daxtheduck'
);
console.log(`Found approved review from daxtheduck: ${hasApprovedReview}`);
core.setOutput('has_approved_review', hasApprovedReview);
- name: Auto approve
if: steps.approval.outputs.approved == 'true' && steps.check_files.outputs.files_valid == 'true' && steps.check_reviews.outputs.has_approved_review == 'false'
run: |
gh pr review --approve "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GITHUB_TOKEN: ${{ secrets.PRIVACY_CONFIG_PAT }}
# Sync Asana tasks for PRs that need manual review (non-auto-approved)
# Task closure on merge is handled by the dedicated close_asana_on_merge job
- uses: duckduckgo/action-asana-sync@v11
if: |
github.event.action != 'closed' &&
((steps.approval.outputs.approved == 'true' && steps.check_files.outputs.files_valid == 'true') != true)
with:
ASANA_ACCESS_TOKEN: ${{ secrets.ASANA_ACCESS_TOKEN }}
ASANA_WORKSPACE_ID: ${{ secrets.ASANA_WORKSPACE_ID }}
ASANA_PROJECT_ID: '1206780406371845'
GITHUB_PAT: ${{ secrets.GH_RO_PAT }}
USER_MAP: ${{ vars.USER_MAP }}
ASSIGN_PR_AUTHOR: 'true'
- name: Create comment
if: github.event.action == 'opened' && (steps.approval.outputs.approved == 'true' && steps.check_files.outputs.files_valid == 'true') != true
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
👋 Don't forget to **add an individual reviewer** (in addition to those auto-added), as this will create a task for them in Asana.
- The best reviewer is most likely a feature or platform owner.
- If they've got permission to approve, you're good to merge. See [CODEOWNERS](https://github.com/duckduckgo/privacy-configuration/blob/main/CODEOWNERS)
- As a fallback the Global owners are:
- [Breakage AOR](https://github.com/orgs/duckduckgo/teams/breakage-aor)
- [Breakage triagers](https://github.com/orgs/duckduckgo/teams/breakage)
- [Config AOR](https://github.com/orgs/duckduckgo/teams/config-aor)
👉 Please mark this as DRAFT unless there's an intention to merge this immediately.
👉 Click "Merge when ready" if you're happy for this to be automatically merged once reviewed. (If not available, ensure you've signed in to DuckDuckGo oauth.)
👉 Don't forget to add schema changes to validate if you're adding/changing a feature.
- [Config Reviewer Documentation](https://github.com/duckduckgo/privacy-configuration/blob/main/docs/config-reviewer-documentation.md)
- [Config Maintainer Documentation](https://github.com/duckduckgo/privacy-configuration/blob/main/docs/config-maintainer-documentation.md)
- [Feature Implementer Documentation](https://github.com/duckduckgo/privacy-configuration/blob/main/docs/feature-implementer-documentation.md)
- name: Create Approval Comment Body
uses: actions/github-script@v9
id: create_approval_body
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const fs = require('fs');
const approvalOutput = fs.readFileSync('approval_output.txt', 'utf8');
let commentBody = `
### [JSON approval analysis](https://github.com/duckduckgo/privacy-configuration/blob/main/.github/workflows/auto-respond-pr.yml#L5-L12):
*Time updated:* ${new Date().toUTCString()}
${approvalOutput}
`
if (commentBody.length > 65536) {
commentBody = '❌ Approval analysis output is too large to post as a comment, run locally to see the analysis and validate'
}
core.setOutput('comment_body', commentBody);
- name: Create, or Update the Diff Comment
uses: peter-evans/create-or-update-comment@v5
with:
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find_diff_comment.outputs.comment-id }}
body: ${{ steps.create_diff_body.outputs.comment_body }}
edit-mode: replace
# Uses PAT (not GITHUB_TOKEN) so this comment triggers issue_comment
# events for downstream workflows (e.g., auto-notify-mattermost.yml).
# See: https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow
- name: Create, or Update the Approval Comment
uses: peter-evans/create-or-update-comment@v5
with:
token: ${{ secrets.PRIVACY_CONFIG_PAT }}
issue-number: ${{ github.event.pull_request.number }}
comment-id: ${{ steps.find_approval_comment.outputs.comment-id }}
body: ${{ steps.create_approval_body.outputs.comment_body }}
edit-mode: replace