mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c0e9c6fd9 |
Generated
+213
-301
@@ -5,7 +5,7 @@
|
||||
#
|
||||
# Source: githubnext/agentics/workflows/issue-triage.md@0837fb7b24c3b84ee77fb7c8cfa8735c48be347a
|
||||
#
|
||||
# Effective stop-time: 2025-12-03 20:01:19
|
||||
# Effective stop-time: 2025-11-27 03:00:29
|
||||
#
|
||||
# Job Dependency Graph:
|
||||
# ```mermaid
|
||||
@@ -33,29 +33,18 @@
|
||||
# add_labels --> update_reaction
|
||||
# missing_tool --> update_reaction
|
||||
# ```
|
||||
#
|
||||
# Pinned GitHub Actions:
|
||||
# - actions/checkout@v5 (08c6903cd8c0fde910a37f88322edcfb5dd907a8)
|
||||
# https://github.com/actions/checkout/commit/08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
# - actions/download-artifact@v5 (634f93cb2916e3fdff6788551b99b062d0335ce0)
|
||||
# https://github.com/actions/download-artifact/commit/634f93cb2916e3fdff6788551b99b062d0335ce0
|
||||
# - actions/github-script@v8 (ed597411d8f924073f98dfc5c65a23a2325f34cd)
|
||||
# https://github.com/actions/github-script/commit/ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
# - actions/setup-node@v6 (2028fbc5c25fe9cf00d9f06a71cc4710d4507903)
|
||||
# https://github.com/actions/setup-node/commit/2028fbc5c25fe9cf00d9f06a71cc4710d4507903
|
||||
# - actions/upload-artifact@v4 (ea165f8d65b6e75b540449e92b4886f43607fa02)
|
||||
# https://github.com/actions/upload-artifact/commit/ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
|
||||
name: "Agentic Triage"
|
||||
"on":
|
||||
schedule:
|
||||
- cron: 0 0 * * *
|
||||
workflow_dispatch: null
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
- reopened
|
||||
|
||||
permissions: read-all
|
||||
|
||||
concurrency:
|
||||
group: "gh-aw-${{ github.workflow }}"
|
||||
group: "gh-aw-${{ github.workflow }}-${{ github.event.issue.number }}"
|
||||
|
||||
run-name: "Agentic Triage"
|
||||
|
||||
@@ -63,7 +52,7 @@ jobs:
|
||||
activation:
|
||||
needs: pre_activation
|
||||
if: needs.pre_activation.outputs.activated == 'true'
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
discussions: write
|
||||
issues: write
|
||||
@@ -74,82 +63,24 @@ jobs:
|
||||
comment_url: ${{ steps.react.outputs.comment-url }}
|
||||
reaction_id: ${{ steps.react.outputs.reaction-id }}
|
||||
steps:
|
||||
- name: Checkout workflows
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github/workflows
|
||||
sparse-checkout-cone-mode: false
|
||||
fetch-depth: 1
|
||||
persist-credentials: false
|
||||
- name: Check workflow file timestamps
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
env:
|
||||
GH_AW_WORKFLOW_FILE: "issue-triage.lock.yml"
|
||||
with:
|
||||
script: |
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
async function main() {
|
||||
const workspace = process.env.GITHUB_WORKSPACE;
|
||||
const workflowFile = process.env.GH_AW_WORKFLOW_FILE;
|
||||
if (!workspace) {
|
||||
core.setFailed("Configuration error: GITHUB_WORKSPACE not available.");
|
||||
return;
|
||||
}
|
||||
if (!workflowFile) {
|
||||
core.setFailed("Configuration error: GH_AW_WORKFLOW_FILE not available.");
|
||||
return;
|
||||
}
|
||||
const workflowBasename = path.basename(workflowFile, ".lock.yml");
|
||||
const workflowMdFile = path.join(workspace, ".github", "workflows", `${workflowBasename}.md`);
|
||||
const lockFile = path.join(workspace, ".github", "workflows", workflowFile);
|
||||
core.info(`Checking workflow timestamps:`);
|
||||
core.info(` Source: ${workflowMdFile}`);
|
||||
core.info(` Lock file: ${lockFile}`);
|
||||
let workflowExists = false;
|
||||
let lockExists = false;
|
||||
try {
|
||||
fs.accessSync(workflowMdFile, fs.constants.F_OK);
|
||||
workflowExists = true;
|
||||
} catch (error) {
|
||||
core.info(`Source file does not exist: ${workflowMdFile}`);
|
||||
}
|
||||
try {
|
||||
fs.accessSync(lockFile, fs.constants.F_OK);
|
||||
lockExists = true;
|
||||
} catch (error) {
|
||||
core.info(`Lock file does not exist: ${lockFile}`);
|
||||
}
|
||||
if (!workflowExists || !lockExists) {
|
||||
core.info("Skipping timestamp check - one or both files not found");
|
||||
return;
|
||||
}
|
||||
const workflowStat = fs.statSync(workflowMdFile);
|
||||
const lockStat = fs.statSync(lockFile);
|
||||
const workflowMtime = workflowStat.mtime.getTime();
|
||||
const lockMtime = lockStat.mtime.getTime();
|
||||
core.info(` Source modified: ${workflowStat.mtime.toISOString()}`);
|
||||
core.info(` Lock modified: ${lockStat.mtime.toISOString()}`);
|
||||
if (workflowMtime > lockMtime) {
|
||||
const warningMessage = `🔴🔴🔴 WARNING: Lock file '${lockFile}' is outdated! The workflow file '${workflowMdFile}' has been modified more recently. Run 'gh aw compile' to regenerate the lock file.`;
|
||||
core.error(warningMessage);
|
||||
await core.summary
|
||||
.addRaw("## ⚠️ Workflow Lock File Warning\n\n")
|
||||
.addRaw(`🔴🔴🔴 **WARNING**: Lock file \`${lockFile}\` is outdated!\n\n`)
|
||||
.addRaw(`The workflow file \`${workflowMdFile}\` has been modified more recently.\n\n`)
|
||||
.addRaw("Run `gh aw compile` to regenerate the lock file.\n\n")
|
||||
.write();
|
||||
} else {
|
||||
core.info("✅ Lock file is up to date");
|
||||
}
|
||||
}
|
||||
main().catch(error => {
|
||||
core.setFailed(error instanceof Error ? error.message : String(error));
|
||||
});
|
||||
run: |
|
||||
WORKFLOW_FILE="${GITHUB_WORKSPACE}/.github/workflows/$(basename "$GITHUB_WORKFLOW" .lock.yml).md"
|
||||
LOCK_FILE="${GITHUB_WORKSPACE}/.github/workflows/$GITHUB_WORKFLOW"
|
||||
|
||||
if [ -f "$WORKFLOW_FILE" ] && [ -f "$LOCK_FILE" ]; then
|
||||
if [ "$WORKFLOW_FILE" -nt "$LOCK_FILE" ]; then
|
||||
echo "🔴🔴🔴 WARNING: Lock file '$LOCK_FILE' is outdated! The workflow file '$WORKFLOW_FILE' has been modified more recently. Run 'gh aw compile' to regenerate the lock file." >&2
|
||||
echo "## ⚠️ Workflow Lock File Warning" >> $GITHUB_STEP_SUMMARY
|
||||
echo "🔴🔴🔴 **WARNING**: Lock file \`$LOCK_FILE\` is outdated!" >> $GITHUB_STEP_SUMMARY
|
||||
echo "The workflow file \`$WORKFLOW_FILE\` has been modified more recently." >> $GITHUB_STEP_SUMMARY
|
||||
echo "Run \`gh aw compile\` to regenerate the lock file." >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
fi
|
||||
- name: Add eyes reaction to the triggering item
|
||||
id: react
|
||||
if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.id == github.repository_id)
|
||||
if: github.event_name == 'issues' || github.event_name == 'issue_comment' || github.event_name == 'pull_request_review_comment' || github.event_name == 'discussion' || github.event_name == 'discussion_comment' || (github.event_name == 'pull_request') && (github.event.pull_request.head.repo.full_name == github.repository)
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
env:
|
||||
GH_AW_REACTION: eyes
|
||||
@@ -483,9 +414,9 @@ jobs:
|
||||
- agent
|
||||
- detection
|
||||
if: >
|
||||
(((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'add_comment'))) &&
|
||||
(((github.event.issue.number) || (github.event.pull_request.number)) || (github.event.discussion.number))
|
||||
runs-on: ubuntu-slim
|
||||
((!cancelled()) && (contains(needs.agent.outputs.output_types, 'add_comment'))) && (((github.event.issue.number) ||
|
||||
(github.event.pull_request.number)) || (github.event.discussion.number))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
discussions: write
|
||||
@@ -874,9 +805,9 @@ jobs:
|
||||
- agent
|
||||
- detection
|
||||
if: >
|
||||
(((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'add_labels'))) &&
|
||||
((github.event.issue.number) || (github.event.pull_request.number))
|
||||
runs-on: ubuntu-slim
|
||||
((!cancelled()) && (contains(needs.agent.outputs.output_types, 'add_labels'))) && ((github.event.issue.number) ||
|
||||
(github.event.pull_request.number))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
@@ -1115,8 +1046,6 @@ jobs:
|
||||
needs: activation
|
||||
runs-on: ubuntu-latest
|
||||
permissions: read-all
|
||||
concurrency:
|
||||
group: "gh-aw-copilot-${{ github.workflow }}"
|
||||
env:
|
||||
GH_AW_SAFE_OUTPUTS: /tmp/gh-aw/safeoutputs/outputs.jsonl
|
||||
GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"add_labels\":{\"max\":5},\"missing_tool\":{}}"
|
||||
@@ -1126,22 +1055,14 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Create gh-aw temp directory
|
||||
run: |
|
||||
mkdir -p /tmp/gh-aw/agent
|
||||
echo "Created /tmp/gh-aw/agent directory for agentic workflow temporary files"
|
||||
- name: Configure Git credentials
|
||||
env:
|
||||
REPO_NAME: ${{ github.repository }}
|
||||
run: |
|
||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||
git config --global user.name "github-actions[bot]"
|
||||
# Re-authenticate git with GitHub token
|
||||
SERVER_URL="${{ github.server_url }}"
|
||||
SERVER_URL="${SERVER_URL#https://}"
|
||||
git remote set-url origin "https://x-access-token:${{ github.token }}@${SERVER_URL}/${REPO_NAME}.git"
|
||||
git config --global user.name "${{ github.workflow }}"
|
||||
echo "Git configured with standard GitHub Actions identity"
|
||||
- name: Checkout PR branch
|
||||
if: |
|
||||
@@ -1193,15 +1114,15 @@ jobs:
|
||||
env:
|
||||
COPILOT_CLI_TOKEN: ${{ secrets.COPILOT_CLI_TOKEN }}
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: '24'
|
||||
- name: Install GitHub Copilot CLI
|
||||
run: npm install -g @github/copilot@0.0.353
|
||||
run: npm install -g @github/copilot@0.0.351
|
||||
- name: Downloading container images
|
||||
run: |
|
||||
set -e
|
||||
docker pull ghcr.io/github/github-mcp-server:v0.20.1
|
||||
docker pull ghcr.io/github/github-mcp-server:v0.19.1
|
||||
docker pull mcp/fetch
|
||||
- name: Setup Safe Outputs Collector MCP
|
||||
run: |
|
||||
@@ -1992,13 +1913,6 @@ jobs:
|
||||
chmod +x /tmp/gh-aw/safeoutputs/mcp-server.cjs
|
||||
|
||||
- name: Setup MCPs
|
||||
env:
|
||||
GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
|
||||
GH_AW_SAFE_OUTPUTS_CONFIG: ${{ toJSON(env.GH_AW_SAFE_OUTPUTS_CONFIG) }}
|
||||
GH_AW_ASSETS_BRANCH: ${{ env.GH_AW_ASSETS_BRANCH }}
|
||||
GH_AW_ASSETS_MAX_SIZE_KB: ${{ env.GH_AW_ASSETS_MAX_SIZE_KB }}
|
||||
GH_AW_ASSETS_ALLOWED_EXTS: ${{ env.GH_AW_ASSETS_ALLOWED_EXTS }}
|
||||
run: |
|
||||
mkdir -p /tmp/gh-aw/mcp-config
|
||||
mkdir -p /home/runner/.copilot
|
||||
@@ -2018,7 +1932,7 @@ jobs:
|
||||
"GITHUB_READ_ONLY=1",
|
||||
"-e",
|
||||
"GITHUB_TOOLSETS=default",
|
||||
"ghcr.io/github/github-mcp-server:v0.20.1"
|
||||
"ghcr.io/github/github-mcp-server:v0.19.1"
|
||||
],
|
||||
"tools": ["*"],
|
||||
"env": {
|
||||
@@ -2035,9 +1949,7 @@ jobs:
|
||||
"GH_AW_SAFE_OUTPUTS_CONFIG": "\${GH_AW_SAFE_OUTPUTS_CONFIG}",
|
||||
"GH_AW_ASSETS_BRANCH": "\${GH_AW_ASSETS_BRANCH}",
|
||||
"GH_AW_ASSETS_MAX_SIZE_KB": "\${GH_AW_ASSETS_MAX_SIZE_KB}",
|
||||
"GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}",
|
||||
"GITHUB_REPOSITORY": "\${GITHUB_REPOSITORY}",
|
||||
"GITHUB_SERVER_URL": "\${GITHUB_SERVER_URL}"
|
||||
"GH_AW_ASSETS_ALLOWED_EXTS": "\${GH_AW_ASSETS_ALLOWED_EXTS}"
|
||||
}
|
||||
},
|
||||
"web-fetch": {
|
||||
@@ -2066,28 +1978,25 @@ jobs:
|
||||
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
|
||||
run: |
|
||||
mkdir -p $(dirname "$GH_AW_PROMPT")
|
||||
cat > "$GH_AW_PROMPT" << 'PROMPT_EOF'
|
||||
cat > $GH_AW_PROMPT << 'PROMPT_EOF'
|
||||
# Agentic Triage
|
||||
|
||||
|
||||
|
||||
You're a triage assistant for GitHub issues. Your task is to analyze issues created in the last 24 hours and perform initial triage tasks for each of them.
|
||||
You're a triage assistant for GitHub issues. Your task is to analyze issue #${{ github.event.issue.number }} and perform some initial triage tasks related to that issue.
|
||||
|
||||
1. First, use the `list_issues` tool to retrieve all issues created in the last 24 hours. Filter issues by using the `since` parameter with a timestamp from 24 hours ago (calculate: current time minus 24 hours in ISO 8601 format).
|
||||
1. Select appropriate labels for the issue from the provided list.
|
||||
|
||||
2. For each issue found, perform the following triage tasks:
|
||||
2. Retrieve the issue content using the `get_issue` tool. If the issue is obviously spam, or generated by bot, or something else that is not an actual issue to be worked on, then add an issue comment to the issue with a one sentence analysis and exit the workflow.
|
||||
|
||||
3. Select appropriate labels for the issue from the provided list.
|
||||
|
||||
4. Retrieve the issue content using the `get_issue` tool. If the issue is obviously spam, or generated by bot, or something else that is not an actual issue to be worked on, then add an issue comment to the issue with a one sentence analysis and move to the next issue.
|
||||
|
||||
5. Next, use the GitHub tools to gather additional context about the issue:
|
||||
3. Next, use the GitHub tools to gather additional context about the issue:
|
||||
|
||||
- Fetch the list of labels available in this repository. Use 'gh label list' bash command to fetch the labels. This will give you the labels you can use for triaging issues.
|
||||
- Fetch any comments on the issue using the `get_issue_comments` tool
|
||||
- **Search for duplicate and related issues**: Use the `search_issues` tool to find similar issues by searching for key terms from the issue title and description. Look for both open and closed issues that might be related or duplicates.
|
||||
- Find similar issues if needed using the `search_issues` tool
|
||||
- List the issues to see other open issues in the repository using the `list_issues` tool
|
||||
|
||||
6. Analyze the issue content, considering:
|
||||
4. Analyze the issue content, considering:
|
||||
|
||||
- The issue title and description
|
||||
- The type of issue (bug report, feature request, question, etc.)
|
||||
@@ -2096,9 +2005,9 @@ jobs:
|
||||
- User impact
|
||||
- Components affected
|
||||
|
||||
7. Write notes, ideas, nudges, resource links, debugging strategies and/or reproduction steps for the team to consider relevant to the issue.
|
||||
5. Write notes, ideas, nudges, resource links, debugging strategies and/or reproduction steps for the team to consider relevant to the issue.
|
||||
|
||||
8. Select appropriate labels from the available labels list provided above:
|
||||
6. Select appropriate labels from the available labels list provided above:
|
||||
|
||||
- Choose labels that accurately reflect the issue's nature
|
||||
- Be specific but comprehensive
|
||||
@@ -2108,16 +2017,15 @@ jobs:
|
||||
- Only select labels from the provided list above
|
||||
- It's okay to not add any labels if none are clearly applicable
|
||||
|
||||
9. Apply the selected labels:
|
||||
7. Apply the selected labels:
|
||||
|
||||
- Use the `update_issue` tool to apply the labels to the issue
|
||||
- DO NOT communicate directly with users
|
||||
- If no labels are clearly applicable, do not apply any labels
|
||||
|
||||
10. Add an issue comment to the issue with your analysis:
|
||||
8. Add an issue comment to the issue with your analysis:
|
||||
- Start with "🎯 Agentic Issue Triage"
|
||||
- Provide a brief summary of the issue
|
||||
- **If duplicate or related issues were found**, add a section listing them with links (e.g., "### 🔗 Potentially Related Issues" followed by a bullet list of related issues with their titles and links)
|
||||
- Mention any relevant details that might help the team understand the issue better
|
||||
- Include any debugging strategies or reproduction steps if applicable
|
||||
- Suggest resources or links that might be helpful for resolving the issue or learning skills related to the issue or the particular area of the codebase affected by it
|
||||
@@ -2127,14 +2035,12 @@ jobs:
|
||||
- If appropriate break the issue down to sub-tasks and write a checklist of things to do.
|
||||
- Use collapsed-by-default sections in the GitHub markdown to keep the comment tidy. Collapse all sections except the short main summary at the top.
|
||||
|
||||
11. After processing all issues, provide a summary of how many issues were triaged. If no issues were created in the last 24 hours, simply note that no new issues needed triage.
|
||||
|
||||
PROMPT_EOF
|
||||
- name: Append XPIA security instructions to prompt
|
||||
env:
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
run: |
|
||||
cat >> "$GH_AW_PROMPT" << 'PROMPT_EOF'
|
||||
cat >> $GH_AW_PROMPT << 'PROMPT_EOF'
|
||||
|
||||
---
|
||||
|
||||
@@ -2166,7 +2072,7 @@ jobs:
|
||||
env:
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
run: |
|
||||
cat >> "$GH_AW_PROMPT" << 'PROMPT_EOF'
|
||||
cat >> $GH_AW_PROMPT << 'PROMPT_EOF'
|
||||
|
||||
---
|
||||
|
||||
@@ -2179,7 +2085,7 @@ jobs:
|
||||
env:
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
run: |
|
||||
cat >> "$GH_AW_PROMPT" << 'PROMPT_EOF'
|
||||
cat >> $GH_AW_PROMPT << 'PROMPT_EOF'
|
||||
|
||||
---
|
||||
|
||||
@@ -2204,7 +2110,7 @@ jobs:
|
||||
env:
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
run: |
|
||||
cat >> "$GH_AW_PROMPT" << 'PROMPT_EOF'
|
||||
cat >> $GH_AW_PROMPT << 'PROMPT_EOF'
|
||||
|
||||
---
|
||||
|
||||
@@ -2273,14 +2179,14 @@ jobs:
|
||||
env:
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
run: |
|
||||
echo "<details>" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "<summary>Generated Prompt</summary>" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo '```markdown' >> "$GITHUB_STEP_SUMMARY"
|
||||
cat "$GH_AW_PROMPT" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo '```' >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "</details>" >> "$GITHUB_STEP_SUMMARY"
|
||||
echo "<details>" >> $GITHUB_STEP_SUMMARY
|
||||
echo "<summary>Generated Prompt</summary>" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo '```markdown' >> $GITHUB_STEP_SUMMARY
|
||||
cat $GH_AW_PROMPT >> $GITHUB_STEP_SUMMARY
|
||||
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "</details>" >> $GITHUB_STEP_SUMMARY
|
||||
- name: Upload prompt
|
||||
if: always()
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
|
||||
@@ -2288,6 +2194,13 @@ jobs:
|
||||
name: prompt.txt
|
||||
path: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
if-no-files-found: warn
|
||||
- name: Capture agent version
|
||||
run: |
|
||||
VERSION_OUTPUT=$(copilot --version 2>&1 || echo "unknown")
|
||||
# Extract semantic version pattern (e.g., 1.2.3, v1.2.3-beta)
|
||||
CLEAN_VERSION=$(echo "$VERSION_OUTPUT" | grep -oE 'v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+)?' | head -n1 || echo "unknown")
|
||||
echo "AGENT_VERSION=$CLEAN_VERSION" >> $GITHUB_ENV
|
||||
echo "Agent version: $VERSION_OUTPUT"
|
||||
- name: Generate agentic run info
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
with:
|
||||
@@ -2299,7 +2212,7 @@ jobs:
|
||||
engine_name: "GitHub Copilot CLI",
|
||||
model: "",
|
||||
version: "",
|
||||
agent_version: "0.0.353",
|
||||
agent_version: process.env.AGENT_VERSION || "",
|
||||
workflow_name: "Agentic Triage",
|
||||
experimental: false,
|
||||
supports_tools_allowlist: true,
|
||||
@@ -2313,9 +2226,6 @@ jobs:
|
||||
actor: context.actor,
|
||||
event_name: context.eventName,
|
||||
staged: false,
|
||||
steps: {
|
||||
firewall: ""
|
||||
},
|
||||
created_at: new Date().toISOString()
|
||||
};
|
||||
|
||||
@@ -2352,12 +2262,9 @@ jobs:
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
GH_AW_SAFE_OUTPUTS: ${{ env.GH_AW_SAFE_OUTPUTS }}
|
||||
GH_AW_SAFE_OUTPUTS_CONFIG: "{\"add_comment\":{\"max\":1},\"add_labels\":{\"max\":5},\"missing_tool\":{}}"
|
||||
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
||||
GITHUB_MCP_SERVER_TOKEN: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||||
GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }}
|
||||
GITHUB_TOKEN: ${{ secrets.COPILOT_CLI_TOKEN }}
|
||||
GITHUB_WORKSPACE: ${{ github.workspace }}
|
||||
XDG_CONFIG_HOME: /home/runner
|
||||
- name: Redact secrets in logs
|
||||
if: always()
|
||||
@@ -2492,135 +2399,71 @@ jobs:
|
||||
script: |
|
||||
async function main() {
|
||||
const fs = require("fs");
|
||||
function sanitizeContent(content, maxLength) {
|
||||
if (!content || typeof content !== "string") {
|
||||
return "";
|
||||
}
|
||||
const allowedDomainsEnv = process.env.GH_AW_ALLOWED_DOMAINS;
|
||||
const defaultAllowedDomains = ["github.com", "github.io", "githubusercontent.com", "githubassets.com", "github.dev", "codespaces.new"];
|
||||
const allowedDomains = allowedDomainsEnv
|
||||
? allowedDomainsEnv
|
||||
.split(",")
|
||||
.map(d => d.trim())
|
||||
.filter(d => d)
|
||||
: defaultAllowedDomains;
|
||||
let sanitized = content;
|
||||
sanitized = neutralizeCommands(sanitized);
|
||||
sanitized = neutralizeMentions(sanitized);
|
||||
sanitized = removeXmlComments(sanitized);
|
||||
sanitized = convertXmlTags(sanitized);
|
||||
sanitized = sanitized.replace(/\x1b\[[0-9;]*[mGKH]/g, "");
|
||||
sanitized = sanitized.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
||||
sanitized = sanitizeUrlProtocols(sanitized);
|
||||
sanitized = sanitizeUrlDomains(sanitized);
|
||||
const lines = sanitized.split("\n");
|
||||
const maxLines = 65000;
|
||||
maxLength = maxLength || 524288;
|
||||
if (lines.length > maxLines) {
|
||||
const truncationMsg = "\n[Content truncated due to line count]";
|
||||
const truncatedLines = lines.slice(0, maxLines).join("\n") + truncationMsg;
|
||||
if (truncatedLines.length > maxLength) {
|
||||
sanitized = truncatedLines.substring(0, maxLength - truncationMsg.length) + truncationMsg;
|
||||
} else {
|
||||
sanitized = truncatedLines;
|
||||
}
|
||||
} else if (sanitized.length > maxLength) {
|
||||
sanitized = sanitized.substring(0, maxLength) + "\n[Content truncated due to length]";
|
||||
}
|
||||
sanitized = neutralizeBotTriggers(sanitized);
|
||||
return sanitized.trim();
|
||||
function sanitizeUrlDomains(s) {
|
||||
s = s.replace(/\bhttps:\/\/([^\s\])}'"<>&\x00-\x1f,;]+)/gi, (match, rest) => {
|
||||
const hostname = rest.split(/[\/:\?#]/)[0].toLowerCase();
|
||||
const isAllowed = allowedDomains.some(allowedDomain => {
|
||||
const normalizedAllowed = allowedDomain.toLowerCase();
|
||||
return hostname === normalizedAllowed || hostname.endsWith("." + normalizedAllowed);
|
||||
});
|
||||
if (isAllowed) {
|
||||
return match;
|
||||
}
|
||||
const domain = hostname;
|
||||
const truncated = domain.length > 12 ? domain.substring(0, 12) + "..." : domain;
|
||||
core.info(`Redacted URL: ${truncated}`);
|
||||
core.debug(`Redacted URL (full): ${match}`);
|
||||
const urlParts = match.split(/([?&#])/);
|
||||
let result = "(redacted)";
|
||||
for (let i = 1; i < urlParts.length; i++) {
|
||||
if (urlParts[i].match(/^[?&#]$/)) {
|
||||
result += urlParts[i];
|
||||
} else {
|
||||
result += sanitizeUrlDomains(urlParts[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
});
|
||||
return s;
|
||||
}
|
||||
function sanitizeUrlProtocols(s) {
|
||||
return s.replace(/(?<![-\/\w])([A-Za-z][A-Za-z0-9+.-]*):(?:\/\/|(?=[^\s:]))[^\s\])}'"<>&\x00-\x1f]+/g, (match, protocol) => {
|
||||
if (protocol.toLowerCase() === "https") {
|
||||
return match;
|
||||
}
|
||||
if (match.includes("::")) {
|
||||
return match;
|
||||
}
|
||||
if (match.includes("://")) {
|
||||
const domainMatch = match.match(/^[^:]+:\/\/([^\/\s?#]+)/);
|
||||
const domain = domainMatch ? domainMatch[1] : match;
|
||||
const truncated = domain.length > 12 ? domain.substring(0, 12) + "..." : domain;
|
||||
core.info(`Redacted URL: ${truncated}`);
|
||||
core.debug(`Redacted URL (full): ${match}`);
|
||||
return "(redacted)";
|
||||
}
|
||||
const dangerousProtocols = ["javascript", "data", "vbscript", "file", "about", "mailto", "tel", "ssh", "ftp"];
|
||||
if (dangerousProtocols.includes(protocol.toLowerCase())) {
|
||||
const truncated = match.length > 12 ? match.substring(0, 12) + "..." : match;
|
||||
core.info(`Redacted URL: ${truncated}`);
|
||||
core.debug(`Redacted URL (full): ${match}`);
|
||||
return "(redacted)";
|
||||
}
|
||||
return match;
|
||||
});
|
||||
}
|
||||
function neutralizeCommands(s) {
|
||||
const commandName = process.env.GH_AW_COMMAND;
|
||||
if (!commandName) {
|
||||
return s;
|
||||
}
|
||||
const escapedCommand = commandName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
return s.replace(new RegExp(`^(\\s*)/(${escapedCommand})\\b`, "i"), "$1`/$2`");
|
||||
}
|
||||
function neutralizeMentions(s) {
|
||||
return s.replace(
|
||||
/(^|[^\w`])@([A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?(?:\/[A-Za-z0-9._-]+)?)/g,
|
||||
(_m, p1, p2) => `${p1}\`@${p2}\``
|
||||
);
|
||||
}
|
||||
function removeXmlComments(s) {
|
||||
return s.replace(/<!--[\s\S]*?-->/g, "").replace(/<!--[\s\S]*?--!>/g, "");
|
||||
}
|
||||
function convertXmlTags(s) {
|
||||
const allowedTags = ["details", "summary", "code", "em", "b"];
|
||||
s = s.replace(/<!\[CDATA\[([\s\S]*?)\]\]>/g, (match, content) => {
|
||||
const convertedContent = content.replace(/<(\/?[A-Za-z][A-Za-z0-9]*(?:[^>]*?))>/g, "($1)");
|
||||
return `(![CDATA[${convertedContent}]])`;
|
||||
});
|
||||
return s.replace(/<(\/?[A-Za-z!][^>]*?)>/g, (match, tagContent) => {
|
||||
const tagNameMatch = tagContent.match(/^\/?\s*([A-Za-z][A-Za-z0-9]*)/);
|
||||
if (tagNameMatch) {
|
||||
const tagName = tagNameMatch[1].toLowerCase();
|
||||
if (allowedTags.includes(tagName)) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
return `(${tagContent})`;
|
||||
});
|
||||
}
|
||||
function neutralizeBotTriggers(s) {
|
||||
return s.replace(/\b(fixes?|closes?|resolves?|fix|close|resolve)\s+#(\w+)/gi, (match, action, ref) => `\`${action} #${ref}\``);
|
||||
}
|
||||
}
|
||||
const maxBodyLength = 65000;
|
||||
function sanitizeContent(content, maxLength) {
|
||||
if (!content || typeof content !== "string") {
|
||||
return "";
|
||||
}
|
||||
const allowedDomainsEnv = process.env.GH_AW_ALLOWED_DOMAINS;
|
||||
const defaultAllowedDomains = ["github.com", "github.io", "githubusercontent.com", "githubassets.com", "github.dev", "codespaces.new"];
|
||||
const allowedDomains = allowedDomainsEnv
|
||||
? allowedDomainsEnv
|
||||
.split(",")
|
||||
.map(d => d.trim())
|
||||
.filter(d => d)
|
||||
: defaultAllowedDomains;
|
||||
let sanitized = content;
|
||||
sanitized = neutralizeMentions(sanitized);
|
||||
sanitized = removeXmlComments(sanitized);
|
||||
sanitized = sanitized.replace(/\x1b\[[0-9;]*[mGKH]/g, "");
|
||||
sanitized = sanitized.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "");
|
||||
sanitized = sanitizeUrlProtocols(sanitized);
|
||||
sanitized = sanitizeUrlDomains(sanitized);
|
||||
const lines = sanitized.split("\n");
|
||||
const maxLines = 65000;
|
||||
maxLength = maxLength || 524288;
|
||||
if (lines.length > maxLines) {
|
||||
const truncationMsg = "\n[Content truncated due to line count]";
|
||||
const truncatedLines = lines.slice(0, maxLines).join("\n") + truncationMsg;
|
||||
if (truncatedLines.length > maxLength) {
|
||||
sanitized = truncatedLines.substring(0, maxLength - truncationMsg.length) + truncationMsg;
|
||||
} else {
|
||||
sanitized = truncatedLines;
|
||||
}
|
||||
} else if (sanitized.length > maxLength) {
|
||||
sanitized = sanitized.substring(0, maxLength) + "\n[Content truncated due to length]";
|
||||
}
|
||||
sanitized = neutralizeBotTriggers(sanitized);
|
||||
return sanitized.trim();
|
||||
function sanitizeUrlDomains(s) {
|
||||
return s.replace(/\bhttps:\/\/[^\s\])}'"<>&\x00-\x1f,;]+/gi, match => {
|
||||
const urlAfterProtocol = match.slice(8);
|
||||
const hostname = urlAfterProtocol.split(/[\/:\?#]/)[0].toLowerCase();
|
||||
const isAllowed = allowedDomains.some(allowedDomain => {
|
||||
const normalizedAllowed = allowedDomain.toLowerCase();
|
||||
return hostname === normalizedAllowed || hostname.endsWith("." + normalizedAllowed);
|
||||
});
|
||||
return isAllowed ? match : "(redacted)";
|
||||
});
|
||||
}
|
||||
function sanitizeUrlProtocols(s) {
|
||||
return s.replace(/\b(\w+):\/\/[^\s\])}'"<>&\x00-\x1f]+/gi, (match, protocol) => {
|
||||
return protocol.toLowerCase() === "https" ? match : "(redacted)";
|
||||
});
|
||||
}
|
||||
function neutralizeMentions(s) {
|
||||
return s.replace(
|
||||
/(^|[^\w`])@([A-Za-z0-9](?:[A-Za-z0-9-]{0,37}[A-Za-z0-9])?(?:\/[A-Za-z0-9._-]+)?)/g,
|
||||
(_m, p1, p2) => `${p1}\`@${p2}\``
|
||||
);
|
||||
}
|
||||
function removeXmlComments(s) {
|
||||
return s.replace(/<!--[\s\S]*?-->/g, "").replace(/<!--[\s\S]*?--!>/g, "");
|
||||
}
|
||||
function neutralizeBotTriggers(s) {
|
||||
return s.replace(/\b(fixes?|closes?|resolves?|fix|close|resolve)\s+#(\w+)/gi, (match, action, ref) => `\`${action} #${ref}\``);
|
||||
}
|
||||
}
|
||||
function getMaxAllowedForType(itemType, config) {
|
||||
const itemConfig = config?.[itemType];
|
||||
if (itemConfig && typeof itemConfig === "object" && "max" in itemConfig && itemConfig.max) {
|
||||
@@ -4452,9 +4295,7 @@ jobs:
|
||||
detection:
|
||||
needs: agent
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
concurrency:
|
||||
group: "gh-aw-copilot-${{ github.workflow }}"
|
||||
permissions: read-all
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- name: Download prompt artifact
|
||||
@@ -4603,11 +4444,11 @@ jobs:
|
||||
env:
|
||||
COPILOT_CLI_TOKEN: ${{ secrets.COPILOT_CLI_TOKEN }}
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
|
||||
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
|
||||
with:
|
||||
node-version: '24'
|
||||
- name: Install GitHub Copilot CLI
|
||||
run: npm install -g @github/copilot@0.0.353
|
||||
run: npm install -g @github/copilot@0.0.351
|
||||
- name: Execute GitHub Copilot CLI
|
||||
id: agentic_execution
|
||||
# Copilot CLI tool arguments (sorted):
|
||||
@@ -4630,11 +4471,8 @@ jobs:
|
||||
env:
|
||||
COPILOT_AGENT_RUNNER_TYPE: STANDALONE
|
||||
GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt
|
||||
GITHUB_HEAD_REF: ${{ github.head_ref }}
|
||||
GITHUB_REF_NAME: ${{ github.ref_name }}
|
||||
GITHUB_STEP_SUMMARY: ${{ env.GITHUB_STEP_SUMMARY }}
|
||||
GITHUB_TOKEN: ${{ secrets.COPILOT_CLI_TOKEN }}
|
||||
GITHUB_WORKSPACE: ${{ github.workspace }}
|
||||
XDG_CONFIG_HOME: /home/runner
|
||||
- name: Parse threat detection results
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
@@ -4684,8 +4522,8 @@ jobs:
|
||||
needs:
|
||||
- agent
|
||||
- detection
|
||||
if: ((!cancelled()) && (needs.agent.result != 'skipped')) && (contains(needs.agent.outputs.output_types, 'missing_tool'))
|
||||
runs-on: ubuntu-slim
|
||||
if: (!cancelled()) && (contains(needs.agent.outputs.output_types, 'missing_tool'))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
timeout-minutes: 5
|
||||
@@ -4813,15 +4651,89 @@ jobs:
|
||||
});
|
||||
|
||||
pre_activation:
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
activated: ${{ steps.check_stop_time.outputs.stop_time_ok == 'true' }}
|
||||
activated: ${{ (steps.check_membership.outputs.is_team_member == 'true') && (steps.check_stop_time.outputs.stop_time_ok == 'true') }}
|
||||
steps:
|
||||
- name: Check team membership for workflow
|
||||
id: check_membership
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
env:
|
||||
GH_AW_REQUIRED_ROLES: admin,maintainer,write
|
||||
with:
|
||||
script: |
|
||||
async function main() {
|
||||
const { eventName } = context;
|
||||
const actor = context.actor;
|
||||
const { owner, repo } = context.repo;
|
||||
const requiredPermissionsEnv = process.env.GH_AW_REQUIRED_ROLES;
|
||||
const requiredPermissions = requiredPermissionsEnv ? requiredPermissionsEnv.split(",").filter(p => p.trim() !== "") : [];
|
||||
if (eventName === "workflow_dispatch") {
|
||||
const hasWriteRole = requiredPermissions.includes("write");
|
||||
if (hasWriteRole) {
|
||||
core.info(`✅ Event ${eventName} does not require validation (write role allowed)`);
|
||||
core.setOutput("is_team_member", "true");
|
||||
core.setOutput("result", "safe_event");
|
||||
return;
|
||||
}
|
||||
core.info(`Event ${eventName} requires validation (write role not allowed)`);
|
||||
}
|
||||
const safeEvents = ["workflow_run", "schedule"];
|
||||
if (safeEvents.includes(eventName)) {
|
||||
core.info(`✅ Event ${eventName} does not require validation`);
|
||||
core.setOutput("is_team_member", "true");
|
||||
core.setOutput("result", "safe_event");
|
||||
return;
|
||||
}
|
||||
if (!requiredPermissions || requiredPermissions.length === 0) {
|
||||
core.warning("❌ Configuration error: Required permissions not specified. Contact repository administrator.");
|
||||
core.setOutput("is_team_member", "false");
|
||||
core.setOutput("result", "config_error");
|
||||
core.setOutput("error_message", "Configuration error: Required permissions not specified");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
core.info(`Checking if user '${actor}' has required permissions for ${owner}/${repo}`);
|
||||
core.info(`Required permissions: ${requiredPermissions.join(", ")}`);
|
||||
const repoPermission = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
username: actor,
|
||||
});
|
||||
const permission = repoPermission.data.permission;
|
||||
core.info(`Repository permission level: ${permission}`);
|
||||
for (const requiredPerm of requiredPermissions) {
|
||||
if (permission === requiredPerm || (requiredPerm === "maintainer" && permission === "maintain")) {
|
||||
core.info(`✅ User has ${permission} access to repository`);
|
||||
core.setOutput("is_team_member", "true");
|
||||
core.setOutput("result", "authorized");
|
||||
core.setOutput("user_permission", permission);
|
||||
return;
|
||||
}
|
||||
}
|
||||
core.warning(`User permission '${permission}' does not meet requirements: ${requiredPermissions.join(", ")}`);
|
||||
core.setOutput("is_team_member", "false");
|
||||
core.setOutput("result", "insufficient_permissions");
|
||||
core.setOutput("user_permission", permission);
|
||||
core.setOutput(
|
||||
"error_message",
|
||||
`Access denied: User '${actor}' is not authorized. Required permissions: ${requiredPermissions.join(", ")}`
|
||||
);
|
||||
} catch (repoError) {
|
||||
const errorMessage = repoError instanceof Error ? repoError.message : String(repoError);
|
||||
core.warning(`Repository permission check failed: ${errorMessage}`);
|
||||
core.setOutput("is_team_member", "false");
|
||||
core.setOutput("result", "api_error");
|
||||
core.setOutput("error_message", `Repository permission check failed: ${errorMessage}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
await main();
|
||||
- name: Check stop-time limit
|
||||
id: check_stop_time
|
||||
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd
|
||||
env:
|
||||
GH_AW_STOP_TIME: 2025-12-03 20:01:19
|
||||
GH_AW_STOP_TIME: 2025-11-27 03:00:29
|
||||
GH_AW_WORKFLOW_NAME: "Agentic Triage"
|
||||
with:
|
||||
script: |
|
||||
@@ -4864,7 +4776,7 @@ jobs:
|
||||
if: >
|
||||
(((((always()) && (needs.agent.result != 'skipped')) && (needs.activation.outputs.comment_id)) && (!contains(needs.agent.outputs.output_types, 'add_comment'))) &&
|
||||
(!contains(needs.agent.outputs.output_types, 'create_pull_request'))) && (!contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch'))
|
||||
runs-on: ubuntu-slim
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
discussions: write
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
---
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # Run daily at midnight UTC
|
||||
workflow_dispatch: # Enable manual trigger
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
stop-after: +30d # workflow will no longer trigger after 30 days. Remove this and recompile to run indefinitely
|
||||
reaction: eyes
|
||||
|
||||
@@ -26,23 +25,20 @@ source: githubnext/agentics/workflows/issue-triage.md@0837fb7b24c3b84ee77fb7c8cf
|
||||
|
||||
<!-- Note - this file can be customized to your needs. Replace this section directly, or add further instructions here. After editing run 'gh aw compile' -->
|
||||
|
||||
You're a triage assistant for GitHub issues. Your task is to analyze issues created in the last 24 hours and perform initial triage tasks for each of them.
|
||||
You're a triage assistant for GitHub issues. Your task is to analyze issue #${{ github.event.issue.number }} and perform some initial triage tasks related to that issue.
|
||||
|
||||
1. First, use the `list_issues` tool to retrieve all issues created in the last 24 hours. Filter issues by using the `since` parameter with a timestamp from 24 hours ago (calculate: current time minus 24 hours in ISO 8601 format).
|
||||
1. Select appropriate labels for the issue from the provided list.
|
||||
|
||||
2. For each issue found, perform the following triage tasks:
|
||||
2. Retrieve the issue content using the `get_issue` tool. If the issue is obviously spam, or generated by bot, or something else that is not an actual issue to be worked on, then add an issue comment to the issue with a one sentence analysis and exit the workflow.
|
||||
|
||||
3. Select appropriate labels for the issue from the provided list.
|
||||
|
||||
4. Retrieve the issue content using the `get_issue` tool. If the issue is obviously spam, or generated by bot, or something else that is not an actual issue to be worked on, then add an issue comment to the issue with a one sentence analysis and move to the next issue.
|
||||
|
||||
5. Next, use the GitHub tools to gather additional context about the issue:
|
||||
3. Next, use the GitHub tools to gather additional context about the issue:
|
||||
|
||||
- Fetch the list of labels available in this repository. Use 'gh label list' bash command to fetch the labels. This will give you the labels you can use for triaging issues.
|
||||
- Fetch any comments on the issue using the `get_issue_comments` tool
|
||||
- **Search for duplicate and related issues**: Use the `search_issues` tool to find similar issues by searching for key terms from the issue title and description. Look for both open and closed issues that might be related or duplicates.
|
||||
- Find similar issues if needed using the `search_issues` tool
|
||||
- List the issues to see other open issues in the repository using the `list_issues` tool
|
||||
|
||||
6. Analyze the issue content, considering:
|
||||
4. Analyze the issue content, considering:
|
||||
|
||||
- The issue title and description
|
||||
- The type of issue (bug report, feature request, question, etc.)
|
||||
@@ -51,9 +47,9 @@ You're a triage assistant for GitHub issues. Your task is to analyze issues crea
|
||||
- User impact
|
||||
- Components affected
|
||||
|
||||
7. Write notes, ideas, nudges, resource links, debugging strategies and/or reproduction steps for the team to consider relevant to the issue.
|
||||
5. Write notes, ideas, nudges, resource links, debugging strategies and/or reproduction steps for the team to consider relevant to the issue.
|
||||
|
||||
8. Select appropriate labels from the available labels list provided above:
|
||||
6. Select appropriate labels from the available labels list provided above:
|
||||
|
||||
- Choose labels that accurately reflect the issue's nature
|
||||
- Be specific but comprehensive
|
||||
@@ -63,16 +59,15 @@ You're a triage assistant for GitHub issues. Your task is to analyze issues crea
|
||||
- Only select labels from the provided list above
|
||||
- It's okay to not add any labels if none are clearly applicable
|
||||
|
||||
9. Apply the selected labels:
|
||||
7. Apply the selected labels:
|
||||
|
||||
- Use the `update_issue` tool to apply the labels to the issue
|
||||
- DO NOT communicate directly with users
|
||||
- If no labels are clearly applicable, do not apply any labels
|
||||
|
||||
10. Add an issue comment to the issue with your analysis:
|
||||
8. Add an issue comment to the issue with your analysis:
|
||||
- Start with "🎯 Agentic Issue Triage"
|
||||
- Provide a brief summary of the issue
|
||||
- **If duplicate or related issues were found**, add a section listing them with links (e.g., "### 🔗 Potentially Related Issues" followed by a bullet list of related issues with their titles and links)
|
||||
- Mention any relevant details that might help the team understand the issue better
|
||||
- Include any debugging strategies or reproduction steps if applicable
|
||||
- Suggest resources or links that might be helpful for resolving the issue or learning skills related to the issue or the particular area of the codebase affected by it
|
||||
@@ -81,5 +76,3 @@ You're a triage assistant for GitHub issues. Your task is to analyze issues crea
|
||||
- If you have any debugging strategies, include them in the comment
|
||||
- If appropriate break the issue down to sub-tasks and write a checklist of things to do.
|
||||
- Use collapsed-by-default sections in the GitHub markdown to keep the comment tidy. Collapse all sections except the short main summary at the top.
|
||||
|
||||
11. After processing all issues, provide a summary of how many issues were triaged. If no issues were created in the last 24 hours, simply note that no new issues needed triage.
|
||||
|
||||
@@ -98,7 +98,6 @@ RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/
|
||||
# Enable Extensions
|
||||
RUN if [ "$DEBUG" = "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi
|
||||
RUN if [ "$DEBUG" = "true" ]; then mkdir -p /tmp/xdebug; fi
|
||||
RUN if [ "$DEBUG" = "true" ]; then apk add --update --no-cache openssh-client github-cli; fi
|
||||
RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi
|
||||
RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20230831/xdebug.so; fi
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
> We just announced DB operators for Appwrite Databases - [Learn more](https://appwrite.io/blog/post/announcing-db-operators)
|
||||
> We just announced Transactions API for Appwrite Databases - [Learn more](https://appwrite.io/blog/post/announcing-transactions-api)
|
||||
|
||||
> Appwrite Cloud is now Generally Available - [Learn more](https://appwrite.io/cloud-ga)
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ return [
|
||||
[
|
||||
'key' => 'cli',
|
||||
'name' => 'Command Line',
|
||||
'version' => '11.1.1',
|
||||
'version' => '11.1.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-cli',
|
||||
'package' => 'https://www.npmjs.com/package/appwrite-cli',
|
||||
'enabled' => true,
|
||||
@@ -281,7 +281,7 @@ return [
|
||||
[
|
||||
'key' => 'php',
|
||||
'name' => 'PHP',
|
||||
'version' => '18.0.1',
|
||||
'version' => '17.5.0',
|
||||
'url' => 'https://github.com/appwrite/sdk-for-php',
|
||||
'package' => 'https://packagist.org/packages/appwrite/appwrite',
|
||||
'enabled' => true,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,6 @@ class UseCases
|
||||
public const ECOMMERCE = 'ecommerce';
|
||||
public const DOCUMENTATION = 'documentation';
|
||||
public const BLOG = 'blog';
|
||||
public const AI = 'artificial intelligence';
|
||||
}
|
||||
|
||||
const TEMPLATE_FRAMEWORKS = [
|
||||
@@ -971,7 +970,7 @@ return [
|
||||
'name' => 'TanStack Start starter',
|
||||
'useCases' => [UseCases::STARTER],
|
||||
'tagline' => 'Simple TanStack Start application integrated with Appwrite SDK.',
|
||||
'score' => 9, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'score' => 6, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'screenshotDark' => $url . '/images/sites/templates/starter-for-tanstack-start-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/starter-for-tanstack-start-light.png',
|
||||
'frameworks' => [
|
||||
@@ -1444,32 +1443,4 @@ return [
|
||||
'providerVersion' => '0.3.*',
|
||||
'variables' => []
|
||||
],
|
||||
[
|
||||
'key' => 'text-to-speech',
|
||||
'name' => 'Text-to-speech with ElevenLabs',
|
||||
'tagline' => 'Next.js app that transforms text into natural, human-like speech using ElevenLabs',
|
||||
'score' => 10, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible)
|
||||
'useCases' => [UseCases::AI],
|
||||
'screenshotDark' => $url . '/images/sites/templates/text-to-speech-dark.png',
|
||||
'screenshotLight' => $url . '/images/sites/templates/text-to-speech-light.png',
|
||||
'frameworks' => [
|
||||
getFramework('NEXTJS', [
|
||||
'providerRootDirectory' => './nextjs/text-to-speech',
|
||||
]),
|
||||
],
|
||||
'vcsProvider' => 'github',
|
||||
'providerRepositoryId' => 'templates-for-sites',
|
||||
'providerOwner' => 'appwrite',
|
||||
'providerVersion' => '0.6.*',
|
||||
'variables' => [
|
||||
[
|
||||
'name' => 'ELEVENLABS_API_KEY',
|
||||
'description' => 'Your ElevenLabs API key',
|
||||
'value' => '',
|
||||
'placeholder' => 'sk_.....',
|
||||
'required' => true,
|
||||
'type' => 'password'
|
||||
],
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
@@ -37,6 +37,7 @@ App::get('/v1/locale')
|
||||
$currencies = Config::getParam('locale-currencies');
|
||||
$output = [];
|
||||
$ip = $request->getIP();
|
||||
$time = (60 * 60 * 24 * 45); // 45 days cache
|
||||
|
||||
$output['ip'] = $ip;
|
||||
|
||||
@@ -67,6 +68,10 @@ App::get('/v1/locale')
|
||||
$output['currency'] = $currency;
|
||||
}
|
||||
|
||||
$response
|
||||
->addHeader('Cache-Control', 'public, max-age=' . $time)
|
||||
->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days
|
||||
;
|
||||
$response->dynamic(new Document($output), Response::MODEL_LOCALE);
|
||||
});
|
||||
|
||||
|
||||
@@ -1125,7 +1125,8 @@ App::options()
|
||||
->inject('project')
|
||||
->inject('devKey')
|
||||
->inject('apiKey')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey) {
|
||||
->inject('httpReferrerSafe')
|
||||
->action(function (App $utopia, SwooleRequest $swooleRequest, Request $request, Response $response, Log $log, Database $dbForPlatform, callable $getProjectDB, Event $queueForEvents, StatsUsage $queueForStatsUsage, Func $queueForFunctions, Executor $executor, Reader $geodb, callable $isResourceBlocked, string $previewHostname, Document $project, Document $devKey, ?Key $apiKey, string $httpReferrerSafe) {
|
||||
/*
|
||||
* Appwrite Router
|
||||
*/
|
||||
@@ -1138,21 +1139,20 @@ App::options()
|
||||
}
|
||||
}
|
||||
|
||||
$origin = $request->getOrigin();
|
||||
$allowedOrigin = $httpReferrerSafe;
|
||||
if (!$devKey->isEmpty()) {
|
||||
$allowedOrigin = '*';
|
||||
}
|
||||
|
||||
$response
|
||||
->addHeader('Server', 'Appwrite')
|
||||
->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE')
|
||||
->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent')
|
||||
->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies')
|
||||
->addHeader('Access-Control-Allow-Origin', $origin)
|
||||
->addHeader('Access-Control-Allow-Origin', $allowedOrigin)
|
||||
->addHeader('Access-Control-Allow-Credentials', 'true')
|
||||
->noContent();
|
||||
|
||||
if (!$devKey->isEmpty()) {
|
||||
$response->addHeader('Access-Control-Allow-Origin', '*');
|
||||
}
|
||||
|
||||
/** OPTIONS requests in utopia do not execute shutdown handlers, as a result we need to track the OPTIONS requests explicitly
|
||||
* @see https://github.com/utopia-php/http/blob/0.33.16/src/App.php#L825-L855
|
||||
*/
|
||||
|
||||
@@ -271,8 +271,6 @@ const METRIC_SITES_ID_REQUESTS = 'sites.{siteInternalId}.requests';
|
||||
const METRIC_SITES_ID_INBOUND = 'sites.{siteInternalId}.inbound';
|
||||
const METRIC_SITES_ID_OUTBOUND = 'sites.{siteInternalId}.outbound';
|
||||
const METRIC_AVATARS_SCREENSHOTS_GENERATED = 'avatars.screenshotsGenerated';
|
||||
const METRIC_FUNCTIONS_RUNTIME = 'functions.runtimes.{runtime}';
|
||||
const METRIC_SITES_FRAMEWORK = 'sites.frameworks.{framework}';
|
||||
|
||||
// Resource types
|
||||
const RESOURCE_TYPE_PROJECTS = 'projects';
|
||||
|
||||
@@ -1022,11 +1022,15 @@ App::setResource('httpReferrerSafe', function (Request $request, string $httpRef
|
||||
$protocol = \parse_url($request->getOrigin($httpReferrer), PHP_URL_SCHEME);
|
||||
$port = \parse_url($request->getOrigin($httpReferrer), PHP_URL_PORT);
|
||||
$referrer = (!empty($protocol) ? $protocol : $request->getProtocol()) . '://' . $origin . (!empty($port) ? ':' . $port : '');
|
||||
$method = $request->getMethod();
|
||||
|
||||
// Safe if route is publicly accessible
|
||||
$route = $utopia->getRoute();
|
||||
if ($route->getLabel('origin', false)) {
|
||||
return $referrer;
|
||||
// For OPTIONS requests, there won't be a route registered in Utopia to match against.
|
||||
if ($method !== Request::METHOD_OPTIONS) {
|
||||
// Safe if route is publicly accessible
|
||||
$route = $utopia->getRoute();
|
||||
if ($route->getLabel('origin', false)) {
|
||||
return $referrer;
|
||||
}
|
||||
}
|
||||
|
||||
// Safe if added as web platform
|
||||
|
||||
Generated
+65
-71
@@ -2673,16 +2673,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-client",
|
||||
"version": "v7.3.6",
|
||||
"version": "v7.3.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/http-client.git",
|
||||
"reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de"
|
||||
"reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de",
|
||||
"reference": "3c0a55a2c8e21e30a37022801c11c7ab5a6cb2de",
|
||||
"url": "https://api.github.com/repos/symfony/http-client/zipball/4b62871a01c49457cf2a8e560af7ee8a94b87a62",
|
||||
"reference": "4b62871a01c49457cf2a8e560af7ee8a94b87a62",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2749,7 +2749,7 @@
|
||||
"http"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/http-client/tree/v7.3.6"
|
||||
"source": "https://github.com/symfony/http-client/tree/v7.3.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2769,7 +2769,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-05T17:41:46+00:00"
|
||||
"time": "2025-09-11T10:12:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/http-client-contracts",
|
||||
@@ -3176,16 +3176,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/service-contracts",
|
||||
"version": "v3.6.1",
|
||||
"version": "v3.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/service-contracts.git",
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
|
||||
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3239,7 +3239,7 @@
|
||||
"standards"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
|
||||
"source": "https://github.com/symfony/service-contracts/tree/v3.6.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -3250,16 +3250,12 @@
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-07-15T11:30:57+00:00"
|
||||
"time": "2025-04-25T09:37:31+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tbachert/spi",
|
||||
@@ -3844,16 +3840,16 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/database",
|
||||
"version": "3.2.0",
|
||||
"version": "3.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/database.git",
|
||||
"reference": "f2d01b6b38057891184f62107bf70a55bc2ea068"
|
||||
"reference": "76568b81f25d89fc1e0c53f0370f139130eeb939"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/f2d01b6b38057891184f62107bf70a55bc2ea068",
|
||||
"reference": "f2d01b6b38057891184f62107bf70a55bc2ea068",
|
||||
"url": "https://api.github.com/repos/utopia-php/database/zipball/76568b81f25d89fc1e0c53f0370f139130eeb939",
|
||||
"reference": "76568b81f25d89fc1e0c53f0370f139130eeb939",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3896,9 +3892,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/database/issues",
|
||||
"source": "https://github.com/utopia-php/database/tree/3.2.0"
|
||||
"source": "https://github.com/utopia-php/database/tree/3.1.5"
|
||||
},
|
||||
"time": "2025-11-06T05:41:54+00:00"
|
||||
"time": "2025-11-05T10:17:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/detector",
|
||||
@@ -3947,24 +3943,22 @@
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/dns",
|
||||
"version": "1.1.3",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/utopia-php/dns.git",
|
||||
"reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707"
|
||||
"reference": "d6eca184883262bdcb4261e57491c91b16079b9a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/1e6b4bac735329c9e5ec69a6a5d899ec2d050707",
|
||||
"reference": "1e6b4bac735329c9e5ec69a6a5d899ec2d050707",
|
||||
"url": "https://api.github.com/repos/utopia-php/dns/zipball/d6eca184883262bdcb4261e57491c91b16079b9a",
|
||||
"reference": "d6eca184883262bdcb4261e57491c91b16079b9a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=8.3",
|
||||
"utopia-php/console": "0.0.*",
|
||||
"utopia-php/domains": "0.9.*",
|
||||
"utopia-php/telemetry": "0.1.*",
|
||||
"utopia-php/validators": "^0.0.2"
|
||||
"utopia-php/telemetry": "0.1.*"
|
||||
},
|
||||
"require-dev": {
|
||||
"laravel/pint": "1.25.*",
|
||||
@@ -3998,9 +3992,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/utopia-php/dns/issues",
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.1.3"
|
||||
"source": "https://github.com/utopia-php/dns/tree/1.1.0"
|
||||
},
|
||||
"time": "2025-11-06T19:08:29+00:00"
|
||||
"time": "2025-11-03T22:49:02+00:00"
|
||||
},
|
||||
{
|
||||
"name": "utopia-php/domains",
|
||||
@@ -5383,16 +5377,16 @@
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "appwrite/sdk-generator",
|
||||
"version": "1.5.3",
|
||||
"version": "1.5.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/appwrite/sdk-generator.git",
|
||||
"reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d"
|
||||
"reference": "cd712674e34136f706e9170641ed6f4ce160e772"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d",
|
||||
"reference": "1a7a3b89147aa8c1bde5247f8eeb7e4832c6016d",
|
||||
"url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/cd712674e34136f706e9170641ed6f4ce160e772",
|
||||
"reference": "cd712674e34136f706e9170641ed6f4ce160e772",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5428,9 +5422,9 @@
|
||||
"description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms",
|
||||
"support": {
|
||||
"issues": "https://github.com/appwrite/sdk-generator/issues",
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.5.3"
|
||||
"source": "https://github.com/appwrite/sdk-generator/tree/1.5.1"
|
||||
},
|
||||
"time": "2025-11-10T09:50:41+00:00"
|
||||
"time": "2025-11-04T09:55:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
@@ -6083,24 +6077,24 @@
|
||||
},
|
||||
{
|
||||
"name": "phpbench/container",
|
||||
"version": "2.2.3",
|
||||
"version": "2.2.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpbench/container.git",
|
||||
"reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196"
|
||||
"reference": "a59b929e00b87b532ca6d0edd8eca0967655af33"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpbench/container/zipball/0c7b2d36c1ea53fe27302fb8873ded7172047196",
|
||||
"reference": "0c7b2d36c1ea53fe27302fb8873ded7172047196",
|
||||
"url": "https://api.github.com/repos/phpbench/container/zipball/a59b929e00b87b532ca6d0edd8eca0967655af33",
|
||||
"reference": "a59b929e00b87b532ca6d0edd8eca0967655af33",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0|^2.0",
|
||||
"symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0 || ^8.0"
|
||||
"symfony/options-resolver": "^4.2 || ^5.0 || ^6.0 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"php-cs-fixer/shim": "^3.89",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"phpstan/phpstan": "^0.12.52",
|
||||
"phpunit/phpunit": "^8"
|
||||
},
|
||||
@@ -6128,22 +6122,22 @@
|
||||
"description": "Simple, configurable, service container.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpbench/container/issues",
|
||||
"source": "https://github.com/phpbench/container/tree/2.2.3"
|
||||
"source": "https://github.com/phpbench/container/tree/2.2.2"
|
||||
},
|
||||
"time": "2025-11-06T09:05:13+00:00"
|
||||
"time": "2023-10-30T13:38:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpbench/phpbench",
|
||||
"version": "1.4.3",
|
||||
"version": "1.4.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpbench/phpbench.git",
|
||||
"reference": "b641dde59d969ea42eed70a39f9b51950bc96878"
|
||||
"reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpbench/phpbench/zipball/b641dde59d969ea42eed70a39f9b51950bc96878",
|
||||
"reference": "b641dde59d969ea42eed70a39f9b51950bc96878",
|
||||
"url": "https://api.github.com/repos/phpbench/phpbench/zipball/bb61ae6c54b3d58642be154eb09f4e73c3511018",
|
||||
"reference": "bb61ae6c54b3d58642be154eb09f4e73c3511018",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -6158,26 +6152,26 @@
|
||||
"phpbench/container": "^2.2",
|
||||
"psr/log": "^1.1 || ^2.0 || ^3.0",
|
||||
"seld/jsonlint": "^1.1",
|
||||
"symfony/console": "^6.1 || ^7.0 || ^8.0",
|
||||
"symfony/filesystem": "^6.1 || ^7.0 || ^8.0",
|
||||
"symfony/finder": "^6.1 || ^7.0 || ^8.0",
|
||||
"symfony/options-resolver": "^6.1 || ^7.0 || ^8.0",
|
||||
"symfony/process": "^6.1 || ^7.0 || ^8.0",
|
||||
"symfony/console": "^6.1 || ^7.0",
|
||||
"symfony/filesystem": "^6.1 || ^7.0",
|
||||
"symfony/finder": "^6.1 || ^7.0",
|
||||
"symfony/options-resolver": "^6.1 || ^7.0",
|
||||
"symfony/process": "^6.1 || ^7.0",
|
||||
"webmozart/glob": "^4.6"
|
||||
},
|
||||
"require-dev": {
|
||||
"dantleech/invoke": "^2.0",
|
||||
"ergebnis/composer-normalize": "^2.39",
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
"jangregor/phpstan-prophecy": "^1.0",
|
||||
"php-cs-fixer/shim": "^3.9",
|
||||
"phpspec/prophecy": "^1.22",
|
||||
"phpstan/extension-installer": "^1.1",
|
||||
"phpstan/phpstan": "^1.0",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpunit/phpunit": "^10.4 || ^11.0",
|
||||
"rector/rector": "^1.2",
|
||||
"symfony/error-handler": "^6.1 || ^7.0 || ^8.0",
|
||||
"symfony/var-dumper": "^6.1 || ^7.0 || ^8.0"
|
||||
"symfony/error-handler": "^6.1 || ^7.0",
|
||||
"symfony/var-dumper": "^6.1 || ^7.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-xdebug": "For Xdebug profiling extension."
|
||||
@@ -6220,7 +6214,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/phpbench/phpbench/issues",
|
||||
"source": "https://github.com/phpbench/phpbench/tree/1.4.3"
|
||||
"source": "https://github.com/phpbench/phpbench/tree/1.4.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -6228,7 +6222,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-06T19:07:31+00:00"
|
||||
"time": "2025-10-26T14:21:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
@@ -7877,16 +7871,16 @@
|
||||
},
|
||||
{
|
||||
"name": "symfony/console",
|
||||
"version": "v7.3.6",
|
||||
"version": "v7.3.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/console.git",
|
||||
"reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a"
|
||||
"reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
|
||||
"reference": "c28ad91448f86c5f6d9d2c70f0cf68bf135f252a",
|
||||
"url": "https://api.github.com/repos/symfony/console/zipball/cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
|
||||
"reference": "cdb80fa5869653c83cfe1a9084a673b6daf57ea7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -7951,7 +7945,7 @@
|
||||
"terminal"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/console/tree/v7.3.6"
|
||||
"source": "https://github.com/symfony/console/tree/v7.3.5"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -7971,20 +7965,20 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-04T01:21:42+00:00"
|
||||
"time": "2025-10-14T15:46:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/filesystem",
|
||||
"version": "v7.3.6",
|
||||
"version": "v7.3.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/filesystem.git",
|
||||
"reference": "e9bcfd7837928ab656276fe00464092cc9e1826a"
|
||||
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/e9bcfd7837928ab656276fe00464092cc9e1826a",
|
||||
"reference": "e9bcfd7837928ab656276fe00464092cc9e1826a",
|
||||
"url": "https://api.github.com/repos/symfony/filesystem/zipball/edcbb768a186b5c3f25d0643159a787d3e63b7fd",
|
||||
"reference": "edcbb768a186b5c3f25d0643159a787d3e63b7fd",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -8021,7 +8015,7 @@
|
||||
"description": "Provides basic utilities for the filesystem",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.3.6"
|
||||
"source": "https://github.com/symfony/filesystem/tree/v7.3.2"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -8041,7 +8035,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2025-11-05T09:52:27+00:00"
|
||||
"time": "2025-07-07T08:17:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/finder",
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
services:
|
||||
appwrite:
|
||||
# volumes:
|
||||
# - ~/.ssh:/root/.ssh
|
||||
environment:
|
||||
- GH_TOKEN=
|
||||
- GIT_EMAIL=
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Avatars;
|
||||
use Appwrite\Enums\Theme;
|
||||
use Appwrite\Enums\Timezone;
|
||||
use Appwrite\Enums\Output;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
->setProject('<YOUR_PROJECT_ID>') // Your project ID
|
||||
->setSession(''); // The user session to authenticate with
|
||||
|
||||
$avatars = new Avatars($client);
|
||||
|
||||
$result = $avatars->getScreenshot(
|
||||
url: 'https://example.com',
|
||||
headers: [], // optional
|
||||
viewportWidth: 1, // optional
|
||||
viewportHeight: 1, // optional
|
||||
scale: 0.1, // optional
|
||||
theme: Theme::LIGHT(), // optional
|
||||
userAgent: '<USER_AGENT>', // optional
|
||||
fullpage: false, // optional
|
||||
locale: '<LOCALE>', // optional
|
||||
timezone: Timezone::AFRICAABIDJAN(), // optional
|
||||
latitude: -90, // optional
|
||||
longitude: -180, // optional
|
||||
accuracy: 0, // optional
|
||||
touch: false, // optional
|
||||
permissions: [], // optional
|
||||
sleep: 0, // optional
|
||||
width: 0, // optional
|
||||
height: 0, // optional
|
||||
quality: -1, // optional
|
||||
output: Output::JPG() // optional
|
||||
);
|
||||
@@ -3,7 +3,6 @@
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Databases;
|
||||
use Appwrite\Enums\RelationshipType;
|
||||
use Appwrite\Enums\RelationMutate;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Databases;
|
||||
use Appwrite\Enums\RelationMutate;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Functions;
|
||||
use Appwrite\Enums\ExecutionMethod;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Functions;
|
||||
use Appwrite\Enums\Runtime;
|
||||
use Appwrite\Enums\;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
@@ -14,7 +14,7 @@ $functions = new Functions($client);
|
||||
$result = $functions->create(
|
||||
functionId: '<FUNCTION_ID>',
|
||||
name: '<NAME>',
|
||||
runtime: Runtime::NODE145(),
|
||||
runtime: ::NODE145(),
|
||||
execute: ["any"], // optional
|
||||
events: [], // optional
|
||||
schedule: '', // optional
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Functions;
|
||||
use Appwrite\Enums\DeploymentDownloadType;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Functions;
|
||||
use Appwrite\Enums\Runtime;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
@@ -14,7 +13,7 @@ $functions = new Functions($client);
|
||||
$result = $functions->update(
|
||||
functionId: '<FUNCTION_ID>',
|
||||
name: '<NAME>',
|
||||
runtime: Runtime::NODE145(), // optional
|
||||
runtime: ::NODE145(), // optional
|
||||
execute: ["any"], // optional
|
||||
events: [], // optional
|
||||
schedule: '', // optional
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Health;
|
||||
use Appwrite\Enums\Name;
|
||||
use Appwrite\Enums\;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
@@ -12,6 +12,6 @@ $client = (new Client())
|
||||
$health = new Health($client);
|
||||
|
||||
$result = $health->getFailedJobs(
|
||||
name: Name::V1DATABASE(),
|
||||
name: ::V1DATABASE(),
|
||||
threshold: null // optional
|
||||
);
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Messaging;
|
||||
use Appwrite\Enums\MessagePriority;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Messaging;
|
||||
use Appwrite\Enums\SmtpEncryption;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Messaging;
|
||||
use Appwrite\Enums\MessagePriority;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Messaging;
|
||||
use Appwrite\Enums\SmtpEncryption;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Sites;
|
||||
use Appwrite\Enums\Framework;
|
||||
use Appwrite\Enums\BuildRuntime;
|
||||
use Appwrite\Enums\Adapter;
|
||||
use Appwrite\Enums\;
|
||||
use Appwrite\Enums\;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
@@ -16,15 +15,15 @@ $sites = new Sites($client);
|
||||
$result = $sites->create(
|
||||
siteId: '<SITE_ID>',
|
||||
name: '<NAME>',
|
||||
framework: Framework::ANALOG(),
|
||||
buildRuntime: BuildRuntime::NODE145(),
|
||||
framework: ::ANALOG(),
|
||||
buildRuntime: ::NODE145(),
|
||||
enabled: false, // optional
|
||||
logging: false, // optional
|
||||
timeout: 1, // optional
|
||||
installCommand: '<INSTALL_COMMAND>', // optional
|
||||
buildCommand: '<BUILD_COMMAND>', // optional
|
||||
outputDirectory: '<OUTPUT_DIRECTORY>', // optional
|
||||
adapter: Adapter::STATIC(), // optional
|
||||
adapter: ::STATIC(), // optional
|
||||
installationId: '<INSTALLATION_ID>', // optional
|
||||
fallbackFile: '<FALLBACK_FILE>', // optional
|
||||
providerRepositoryId: '<PROVIDER_REPOSITORY_ID>', // optional
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Sites;
|
||||
use Appwrite\Enums\DeploymentDownloadType;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Sites;
|
||||
use Appwrite\Enums\Framework;
|
||||
use Appwrite\Enums\BuildRuntime;
|
||||
use Appwrite\Enums\Adapter;
|
||||
use Appwrite\Enums\;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
@@ -16,15 +14,15 @@ $sites = new Sites($client);
|
||||
$result = $sites->update(
|
||||
siteId: '<SITE_ID>',
|
||||
name: '<NAME>',
|
||||
framework: Framework::ANALOG(),
|
||||
framework: ::ANALOG(),
|
||||
enabled: false, // optional
|
||||
logging: false, // optional
|
||||
timeout: 1, // optional
|
||||
installCommand: '<INSTALL_COMMAND>', // optional
|
||||
buildCommand: '<BUILD_COMMAND>', // optional
|
||||
outputDirectory: '<OUTPUT_DIRECTORY>', // optional
|
||||
buildRuntime: BuildRuntime::NODE145(), // optional
|
||||
adapter: Adapter::STATIC(), // optional
|
||||
buildRuntime: ::NODE145(), // optional
|
||||
adapter: ::STATIC(), // optional
|
||||
fallbackFile: '<FALLBACK_FILE>', // optional
|
||||
installationId: '<INSTALLATION_ID>', // optional
|
||||
providerRepositoryId: '<PROVIDER_REPOSITORY_ID>', // optional
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Storage;
|
||||
use Appwrite\Enums\Compression;
|
||||
use Appwrite\Permission;
|
||||
use Appwrite\Role;
|
||||
|
||||
@@ -21,7 +20,7 @@ $result = $storage->createBucket(
|
||||
enabled: false, // optional
|
||||
maximumFileSize: 1, // optional
|
||||
allowedFileExtensions: [], // optional
|
||||
compression: Compression::NONE(), // optional
|
||||
compression: ::NONE(), // optional
|
||||
encryption: false, // optional
|
||||
antivirus: false // optional
|
||||
);
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Storage;
|
||||
use Appwrite\Enums\ImageGravity;
|
||||
use Appwrite\Enums\ImageFormat;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Storage;
|
||||
use Appwrite\Enums\Compression;
|
||||
use Appwrite\Permission;
|
||||
use Appwrite\Role;
|
||||
|
||||
@@ -21,7 +20,7 @@ $result = $storage->updateBucket(
|
||||
enabled: false, // optional
|
||||
maximumFileSize: 1, // optional
|
||||
allowedFileExtensions: [], // optional
|
||||
compression: Compression::NONE(), // optional
|
||||
compression: ::NONE(), // optional
|
||||
encryption: false, // optional
|
||||
antivirus: false // optional
|
||||
);
|
||||
@@ -3,7 +3,6 @@
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\TablesDB;
|
||||
use Appwrite\Enums\RelationshipType;
|
||||
use Appwrite\Enums\RelationMutate;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\TablesDB;
|
||||
use Appwrite\Enums\RelationMutate;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
use Appwrite\Client;
|
||||
use Appwrite\Services\Users;
|
||||
use Appwrite\Enums\PasswordHash;
|
||||
|
||||
$client = (new Client())
|
||||
->setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
## 11.1.1
|
||||
|
||||
* Fix duplicate `enums` during type generation by prefixing them with table name. For example, `enum MyEnum` will now be generated as `enum MyTableMyEnum` to avoid conflicts.
|
||||
|
||||
## 11.1.0
|
||||
|
||||
* Add `total` parameter to list queries allowing skipping counting rows in a table for improved performance
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
# Change Log
|
||||
|
||||
## 18.0.1
|
||||
|
||||
* Fix `TablesDB` service to use correct file name
|
||||
|
||||
## 18.0.0
|
||||
|
||||
* Fix duplicate methods issue (e.g., `updateMFA` and `updateMfa`) causing build and runtime errors
|
||||
* Add support for `getScreenshot` method to `Avatars` service
|
||||
* Add `Output`, `Theme` and `Timezone` enums
|
||||
|
||||
## 17.5.0
|
||||
|
||||
* Add `total` parameter to list queries allowing skipping counting rows in a table for improved performance
|
||||
|
||||
@@ -26,27 +26,34 @@ Before releasing SDKs, you need to:
|
||||
|
||||
To enable SDK releases via GitHub, you need to mount SSH keys and configure GitHub authentication in your Docker environment.
|
||||
|
||||
#### Update docker-compose.override.yml
|
||||
#### Update Dockerfile
|
||||
|
||||
Update `docker-compose.override.yml` to mount SSH keys and set environment variables for the `appwrite` service:
|
||||
Add the following configuration to your `Dockerfile`:
|
||||
|
||||
```dockerfile
|
||||
ARG GH_TOKEN
|
||||
ENV GH_TOKEN=your_github_token_here
|
||||
RUN git config --global user.email "your-email@example.com"
|
||||
RUN apk add --update --no-cache openssh-client github-cli
|
||||
```
|
||||
|
||||
Replace:
|
||||
- `your_github_token_here` with your GitHub personal access token (with appropriate permissions)
|
||||
- `your-email@example.com` with your Git email address
|
||||
|
||||
#### Update docker-compose.yml
|
||||
|
||||
Add the SSH key volume mount to the `appwrite` service in `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
appwrite:
|
||||
volumes:
|
||||
- ~/.ssh:/root/.ssh
|
||||
environment:
|
||||
- GH_TOKEN=your_github_token_here
|
||||
- GIT_EMAIL=your-email@example.com
|
||||
# ... other volumes
|
||||
```
|
||||
|
||||
Uncomment the volumes section.
|
||||
|
||||
Replace:
|
||||
- `your_github_token_here` with your GitHub personal access token (with appropriate permissions)
|
||||
- `your-email@example.com` with your Git email address
|
||||
|
||||
This mounts your SSH keys from the host machine and sets the GitHub token and email as environment variables, allowing the container to authenticate with GitHub. The git configuration is handled automatically at runtime.
|
||||
This mounts your SSH keys from the host machine, allowing the container to authenticate with GitHub.
|
||||
|
||||
### Updating Specs
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 288 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 225 KiB |
@@ -53,9 +53,7 @@ class Google extends OAuth2
|
||||
'redirect_uri' => $this->callback,
|
||||
'scope' => \implode(' ', $this->getScopes()),
|
||||
'state' => \json_encode($this->state),
|
||||
'response_type' => 'code',
|
||||
'access_type' => 'offline',
|
||||
'prompt' => 'consent'
|
||||
'response_type' => 'code'
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -427,21 +427,16 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
mkdir -p ' . $target . ' && \
|
||||
cd ' . $target . ' && \
|
||||
git init && \
|
||||
git config core.ignorecase false && \
|
||||
git config pull.rebase false && \
|
||||
git remote add origin ' . $gitUrl . ' && \
|
||||
git fetch origin && \
|
||||
(git checkout -f ' . $repoBranch . ' 2>/dev/null || git checkout -b ' . $repoBranch . ') && \
|
||||
git checkout ' . $repoBranch . ' || git checkout -b ' . $repoBranch . ' && \
|
||||
git pull origin ' . $repoBranch . ' && \
|
||||
(git checkout -f ' . $gitBranch . ' 2>/dev/null || git checkout -b ' . $gitBranch . ') && \
|
||||
(git fetch origin ' . $gitBranch . ' 2>/dev/null || git push -u origin ' . $gitBranch . ') && \
|
||||
git reset --hard origin/' . $gitBranch . ' 2>/dev/null || true && \
|
||||
(test -d .github && cp -r .github /tmp/.github-backup-$$ || true) && \
|
||||
git rm -rf --cached . && \
|
||||
git clean -fdx -e .git -e .github && \
|
||||
git checkout ' . $gitBranch . ' || git checkout -b ' . $gitBranch . ' && \
|
||||
git fetch origin ' . $gitBranch . ' || git push -u origin ' . $gitBranch . ' && \
|
||||
git pull origin ' . $gitBranch . ' && \
|
||||
find . -mindepth 1 ! -path "./.git*" -delete && \
|
||||
cp -r ' . $result . '/. ' . $target . '/ && \
|
||||
(test -d /tmp/.github-backup-$$ && cp -r /tmp/.github-backup-$$/.github . && rm -rf /tmp/.github-backup-$$ || true) && \
|
||||
git add -A && \
|
||||
git add . && \
|
||||
git commit -m "' . $message . '" && \
|
||||
git push -u origin ' . $gitBranch . '
|
||||
');
|
||||
|
||||
@@ -335,11 +335,7 @@ class StatsResources extends Action
|
||||
$this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_DEPLOYMENTS), $deployments);
|
||||
$this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_FUNCTIONS, METRIC_RESOURCE_TYPE_BUILDS), $deployments);
|
||||
|
||||
|
||||
// Count runtimes
|
||||
$runtimes = [];
|
||||
|
||||
$this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $region, &$runtimes) {
|
||||
$this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $region) {
|
||||
$functionDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [
|
||||
Query::equal('resourceInternalId', [$function->getSequence()]),
|
||||
Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]),
|
||||
@@ -368,19 +364,7 @@ class StatsResources extends Action
|
||||
});
|
||||
|
||||
$this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage);
|
||||
|
||||
// Runtimes count
|
||||
$runtime = $function->getAttribute('runtime');
|
||||
if (!empty($runtime)) {
|
||||
$runtimes[$runtime] = ($runtimes[$runtime] ?? 0) + 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Write runtimes counts
|
||||
foreach ($runtimes as $runtime => $count) {
|
||||
$this->createStatsDocuments($region, str_replace('{runtime}', $runtime, METRIC_FUNCTIONS_RUNTIME), $count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected function countForSites(Database $dbForProject, string $region)
|
||||
@@ -401,10 +385,7 @@ class StatsResources extends Action
|
||||
$this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_DEPLOYMENTS), $deployments);
|
||||
$this->createStatsDocuments($region, str_replace("{resourceType}", RESOURCE_TYPE_SITES, METRIC_RESOURCE_TYPE_BUILDS), $deployments);
|
||||
|
||||
// Count frameworks
|
||||
$frameworks = [];
|
||||
|
||||
$this->foreachDocument($dbForProject, 'sites', [], function (Document $site) use ($dbForProject, $region, &$frameworks) {
|
||||
$this->foreachDocument($dbForProject, 'sites', [], function (Document $site) use ($dbForProject, $region) {
|
||||
$siteDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [
|
||||
Query::equal('resourceInternalId', [$site->getSequence()]),
|
||||
Query::equal('resourceType', [RESOURCE_TYPE_SITES]),
|
||||
@@ -429,18 +410,7 @@ class StatsResources extends Action
|
||||
]);
|
||||
|
||||
$this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $siteBuildsStorage);
|
||||
|
||||
// Frameworks count
|
||||
$framework = $site->getAttribute('framework');
|
||||
if (!empty($framework)) {
|
||||
$frameworks[$framework] = ($frameworks[$framework] ?? 0) + 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Write frameworks counts
|
||||
foreach ($frameworks as $framework => $count) {
|
||||
$this->createStatsDocuments($region, str_replace('{framework}', $framework, METRIC_SITES_FRAMEWORK), $count);
|
||||
}
|
||||
}
|
||||
|
||||
protected function createStatsDocuments(string $region, string $metric, int $value)
|
||||
|
||||
@@ -11,36 +11,9 @@ class Comment
|
||||
{
|
||||
// TODO: Add more tips
|
||||
protected array $tips = [
|
||||
'Appwrite has crossed the 50K GitHub stars milestone with hundreds of active contributors',
|
||||
'Our Discord community has grown to 24K developers, and counting',
|
||||
'Sites auto-generate unique domains with the pattern https://randomstring.appwrite.network',
|
||||
'Every Git commit and branch gets its own deployment URL automatically',
|
||||
'Custom domains work with both CNAME for subdomains and NS records for apex domains',
|
||||
'HTTPS and SSL certificates are handled automatically for all your Sites',
|
||||
'Functions can run for up to 15 minutes before timing out',
|
||||
'Schedule functions to run as often as every minute with cron expressions',
|
||||
'Environment variables can be scoped per function or shared across your project',
|
||||
'Function scopes give you fine-grained control over API permissions',
|
||||
'Sites support three domain rule types: Active deployment, Git branch, and Redirect',
|
||||
'Preview deployments create instant URLs for every branch and commit',
|
||||
'Trigger functions via HTTP, SDKs, events, webhooks, or scheduled cron jobs',
|
||||
'Each function runs in its own isolated container with custom environment variables',
|
||||
'Build commands execute in runtime containers during deployment',
|
||||
'Dynamic API keys are generated automatically for each function execution',
|
||||
'JWT tokens let functions act on behalf of users while preserving their permissions',
|
||||
'Storage files get ClamAV malware scanning and encryption by default',
|
||||
'Roll back Sites deployments instantly by switching between versions',
|
||||
'Git integration provides automatic deployments with optional PR comments',
|
||||
'Silent mode disables those chatty PR comments if you prefer peace and quiet',
|
||||
'Environment variable changes require redeployment to take effect',
|
||||
'SSR frameworks are fully supported with configurable build runtimes',
|
||||
'Global CDN and DDoS protection come free with every Sites deployment',
|
||||
'Deploy functions via zip upload or connect directly to your Git repo',
|
||||
'Realtime gives you live updates for users, storage, functions, and databases',
|
||||
'GraphQL API works alongside REST and WebSocket protocols',
|
||||
'Messaging handles push notifications, emails, and SMS through one unified API',
|
||||
'Teams feature lets you group users with membership management and role permissions',
|
||||
'MCP server integration brings LLM superpowers to Claude Desktop and Cursor IDE',
|
||||
'Appwrite has a Discord community with over 16 000 members.',
|
||||
'You can use Avatars API to generate QR code for any text or URLs.',
|
||||
'Cursor pagination performs better than offset pagination when loading further pages.',
|
||||
];
|
||||
|
||||
protected string $statePrefix = '[appwrite]: #';
|
||||
|
||||
Reference in New Issue
Block a user