Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 57 additions & 17 deletions .github/workflows/Deploy-internal.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,49 @@
name: Deploy internal

on:
pull_request:
pull_request_target:
branches:
- main
paths:
- "**/*.jmd"
- "**/Project.toml"

permissions:
contents: write

jobs:
generate-job-strategy-matrix:
runs-on: ubuntu-latest
outputs:
job-strategy-matrix: ${{ steps.generate.outputs.job-strategy-matrix }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Checkout PR code
uses: actions/checkout@v4
with:
fetch-depth: 5
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 2
persist-credentials: false
Comment on lines +4 to +26
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical Security Issue: Using pull_request_target with checkout of untrusted PR code creates a serious security vulnerability. The pull_request_target event runs with write permissions in the context of the base repository and has access to secrets, but this workflow checks out code from the fork (lines 23-24). This allows malicious actors to execute arbitrary code with elevated privileges.

Recommendation: Either:

  1. Use the standard pull_request event instead of pull_request_target if you don't need write permissions during the build phase, OR
  2. If you must use pull_request_target, only checkout the PR code for isolated build steps and ensure no untrusted code runs with elevated permissions. Consider a two-stage approach where untrusted code builds in isolation, then trusted code deploys the artifacts.

Copilot uses AI. Check for mistakes.

- name: Generate MATRIX
id: generate
run: |
MATRIX=$( (
echo '{ "tutorial": ['
git diff --name-only HEAD HEAD~1 | grep -E "(jmd|Project.toml)" | sed 's/Project.toml/index.jmd/g' | uniq | sed -r 's/(.*)/\"\1\"/g' | sed '$!s/$/,/'
git diff --name-only HEAD HEAD~1 \
| grep -E "(jmd|Project.toml)" \
| sed 's/Project.toml/index.jmd/g' \
| uniq \
| sed -r 's/(.*)/\"\1\"/g' \
| sed '$!s/$/,/'
echo ']}'
) | jq -c .)
echo $MATRIX
echo $MATRIX | jq .
echo "::set-output name=job-strategy-matrix::$MATRIX"

echo "$MATRIX"
echo "$MATRIX" | jq .

# new-style output
echo "job-strategy-matrix=$MATRIX" >> "$GITHUB_OUTPUT"

build-tutorials:
needs: generate-job-strategy-matrix
Expand All @@ -36,20 +52,27 @@ jobs:
strategy:
matrix: ${{ fromJSON(needs.generate-job-strategy-matrix.outputs.job-strategy-matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Checkout PR code
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
Comment on lines +55 to +59
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security Issue: Same as above - checking out untrusted PR code (lines 58-59) in a pull_request_target workflow that has write permissions (line 12) creates a security vulnerability. The build script at line 70 will execute code from the potentially malicious PR.

Suggested change
- name: Checkout PR code
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
ref: ${{ github.event.pull_request.head.sha }}
- name: Checkout base repository code
uses: actions/checkout@v4
with:
repository: ${{ github.repository }}
ref: ${{ github.sha }}

Copilot uses AI. Check for mistakes.
fetch-depth: 1
persist-credentials: false

- name: Install Julia
uses: julia-actions/setup-julia@v1
with:
version: 1

- name: Build tutorial
run: |
bash .github/workflows/build_tutorial.sh ${{ matrix.tutorial }}

- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: tutorials
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Artifact Name Conflict: The build-tutorials job runs as a matrix job (line 52-53) which can execute multiple times in parallel, but all instances upload artifacts with the same name "tutorials" (line 75). In upload-artifact@v4, artifacts with the same name will overwrite each other, causing data loss.

Recommendation: Use a unique artifact name for each matrix job, such as:

name: tutorials-${{ hashFiles(matrix.tutorial) }}

or include the tutorial name in the artifact name. Then update the deploy job to download all artifacts using a pattern or merge strategy.

Copilot uses AI. Check for mistakes.
path: markdown/*

deploy:
Expand All @@ -61,38 +84,55 @@ jobs:
run: |
wget https://github.com/JuliaSmoothOptimizers/JSOTutorials.jl/archive/refs/heads/gh-pages.zip
unzip gh-pages.zip

- name: Download artifact
uses: actions/download-artifact@v4
with:
name: tutorials
path: .
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Path Mismatch: The artifact is downloaded to path . (current directory) but the upload at line 76 uses path: markdown/*. When downloaded, the artifact will contain the files from the markdown/ directory directly in the download path. However, line 99 tries to copy from markdown/* which won't exist unless the artifact preserved the directory structure.

Recommendation: Either:

  1. Change the download path to markdown/ to preserve the expected structure, OR
  2. Change line 99 to cp -rf *.md JSOTutorials.jl-gh-pages/ or similar pattern that matches the actual downloaded structure.

Copilot uses AI. Check for mistakes.
- name: list

- name: List files
run: ls -R

- name: Merge gh-pages and updates and update index.md
run: |
cp -rf artifact/* JSOTutorials.jl-gh-pages/
cp -rf markdown/* JSOTutorials.jl-gh-pages/
cd JSOTutorials.jl-gh-pages

echo "## JSOTutorials preview page

For the complete list of tutorials, go to <https://jso.dev/tutorials/>.

" > index.md
for file in **/*.md; do NAME=$(echo $file | cut -d/ -f 1); TITLE=$(grep "title:" $file | cut -d\" -f2); echo "- [$TITLE]($NAME/)"; done >> index.md

Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Bash Option: The script uses **/*.md glob pattern (line 108) which requires the globstar option to be enabled in bash. Without it, ** is treated as a literal string rather than matching directories recursively.

Recommendation: Add shopt -s globstar before the loop:

shopt -s globstar
for file in **/*.md; do
Suggested change
shopt -s globstar

Copilot uses AI. Check for mistakes.
for file in **/*.md; do
NAME=$(echo "$file" | cut -d/ -f 1)
TITLE=$(grep "title:" "$file" | cut -d\" -f2)
echo "- [$TITLE]($NAME/)"
done >> index.md
Comment on lines +108 to +112
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing Error Handling: The loop iterates over **/*.md files without checking if any files exist. If no .md files are found, the loop will process the literal string **/*.md which could cause errors.

Recommendation: Add a check or enable nullglob:

shopt -s nullglob
for file in **/*.md; do
  NAME=$(echo "$file" | cut -d/ -f 1)
  TITLE=$(grep "title:" "$file" | cut -d\" -f2)
  echo "- [$TITLE]($NAME/)"
done >> index.md

Copilot uses AI. Check for mistakes.

- name: Deploy to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./JSOTutorials.jl-gh-pages
enable_jekyll: true

pr_comment:
needs: [generate-job-strategy-matrix, build-tutorials, deploy]
runs-on: ubuntu-latest
if: ${{ needs.generate-job-strategy-matrix.outputs.job-strategy-matrix != '[]' }}
steps:
- name: "Comment PR"
- name: Comment PR
uses: actions/github-script@0.3.0
Copy link

Copilot AI Nov 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outdated Action Version: The actions/github-script@0.3.0 action is severely outdated (released in 2020). The current version is v7, which includes important security updates, bug fixes, and API improvements.

Recommendation: Update to the latest version:

uses: actions/github-script@v7
Suggested change
uses: actions/github-script@0.3.0
uses: actions/github-script@v7

Copilot uses AI. Check for mistakes.
if: github.event_name == 'pull_request' && github.repository == github.event.pull_request.head.repo.full_name # if this is a pull request build AND the pull request is NOT made from a fork
if: github.event_name == 'pull_request_target'
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { issue: { number: issue_number }, repo: { owner, repo } } = context;
github.issues.createComment({ issue_number, owner, repo, body: 'Once the build has completed, you can preview your PR at this URL: https://jso.dev/JSOTutorials.jl/' });
const { issue: { number: issue_number }, repo: { owner, repo } } = context;
github.issues.createComment({
issue_number,
owner,
repo,
body: 'Once the build has completed, you can preview your PR at this URL: https://jso.dev/JSOTutorials.jl/'
});