-
Notifications
You must be signed in to change notification settings - Fork 3
Updating Offline Mode #505
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
674e1c7
184c577
578e404
1d6a49f
67ea9b9
6d311e4
02447c3
64f6a66
43dffca
7bf66b9
5198097
f53844e
a222904
7898a8f
766450d
c153ece
aa1a0af
1691b78
1a34bce
ae8a167
a761475
b66169e
5aebd52
aa4cf8c
a488833
e510aec
bfadfff
59541de
513082d
8b3bd8b
50d8704
76d246a
18d7a1e
0403029
c4410ed
3d612e6
2b10cb1
5b57044
1057545
76402d2
008acf3
6a38380
1e023b3
cfa49d1
6e7f841
f690bf6
9234dd2
bab7bae
3122e3b
eae7332
ca22b80
ee987e3
3ccbbe1
fab5527
e506998
e481a18
a5953b9
3a42155
a571a31
cdb45f2
65e6b13
a78dc1f
fe77851
e3924a9
36389f9
51c018d
e2bf7e6
71f1ea5
8754455
bfcd395
53f7fdf
8dc29ae
a73b9f9
a3d1f38
46fb7da
418ff47
be6bf80
7e7324d
0812bce
3f845bf
bcac56f
563cc8e
74dbe65
a9dc744
e17052e
b086a3d
7e35f6d
9808034
5526712
5aeba61
e79b2e6
e1660bb
cc3fa30
b1cfdb7
c062c78
3cecea6
83b438a
0baab92
9dbd7af
a6ae069
860d331
58946df
7c4a9aa
fa719f0
7995a3f
6bbd1f8
cd9677b
e96aab5
9ae0c43
132d65b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,20 @@ | ||
| NEXT_PUBLIC_API_URL=http://localhost:3000/api | ||
| NEXTAUTH_URL=http://localhost:3000/ | ||
| NEXTAUTH_SECRET=testsecret | ||
|
|
||
| NEXT_PUBLIC_API_URL=/api/ | ||
|
|
||
| DEVELOPER_EMAILS=["test@gmail.com"] | ||
|
|
||
| TOA_URL=https://example.com | ||
| TOA_APP_ID=123 | ||
| TOA_KEY=456 | ||
|
|
||
| DEFAULT_IMAGE=https://example.com/default.jpg | ||
| DEFAULT_IMAGE=https://example.com/default.jpg | ||
|
|
||
| BASE_URL_FOR_PLAYWRIGHT=http://localhost:3000/ | ||
| ENABLE_TEST_SIGNIN_ROUTE=true | ||
| FALLBACK_MONGODB_URI=mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000 | ||
|
|
||
| ENV_FILE=.env.test | ||
|
|
||
| DB=playwright_tests |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||||||||||||||||||||||
| name: Playwright Tests | ||||||||||||||||||||||||||
| on: [workflow_dispatch, workflow_call] | ||||||||||||||||||||||||||
| jobs: | ||||||||||||||||||||||||||
| e2e_tests: | ||||||||||||||||||||||||||
| timeout-minutes: 60 | ||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||
| strategy: | ||||||||||||||||||||||||||
| fail-fast: false | ||||||||||||||||||||||||||
| matrix: | ||||||||||||||||||||||||||
| # Make sure to require each shard in GitHub! | ||||||||||||||||||||||||||
| shardIndex: [1, 2, 3, 4] | ||||||||||||||||||||||||||
| shardTotal: [4] | ||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - uses: actions/setup-node@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| node-version: lts/* | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Install dependencies | ||||||||||||||||||||||||||
| run: npm ci | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Install Playwright browsers | ||||||||||||||||||||||||||
| run: npx playwright install --with-deps | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Start MongoDB | ||||||||||||||||||||||||||
| uses: supercharge/mongodb-github-action@1.12.0 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| mongodb-version: "8.0" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Run Playwright tests | ||||||||||||||||||||||||||
| run: npx cross-env NODE_ENV=test playwright test --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }} | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Upload blob report to GitHub Actions Artifacts | ||||||||||||||||||||||||||
| if: ${{ !cancelled() }} | ||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| name: blob-report-${{ matrix.shardIndex }} | ||||||||||||||||||||||||||
| path: blob-report | ||||||||||||||||||||||||||
| retention-days: 1 | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| merge_reports: | ||||||||||||||||||||||||||
| # Merge reports after playwright-tests, even if some shards have failed | ||||||||||||||||||||||||||
| if: ${{ !cancelled() }} | ||||||||||||||||||||||||||
| needs: [e2e_tests] | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| runs-on: ubuntu-latest | ||||||||||||||||||||||||||
| steps: | ||||||||||||||||||||||||||
| - uses: actions/checkout@v4 | ||||||||||||||||||||||||||
| - uses: actions/setup-node@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| node-version: lts/* | ||||||||||||||||||||||||||
| - name: Install dependencies | ||||||||||||||||||||||||||
| run: npm ci | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Download blob reports from GitHub Actions Artifacts | ||||||||||||||||||||||||||
| uses: actions/download-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| path: all-blob-reports | ||||||||||||||||||||||||||
| pattern: blob-report-* | ||||||||||||||||||||||||||
| merge-multiple: true | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Merge into HTML Report | ||||||||||||||||||||||||||
| run: npx playwright merge-reports --reporter html ./all-blob-reports | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| - name: Upload HTML report | ||||||||||||||||||||||||||
| uses: actions/upload-artifact@v4 | ||||||||||||||||||||||||||
| with: | ||||||||||||||||||||||||||
| name: html-report--attempt-${{ github.run_attempt }} | ||||||||||||||||||||||||||
| path: playwright-report | ||||||||||||||||||||||||||
| retention-days: 14 | ||||||||||||||||||||||||||
|
Comment on lines
+44
to
+71
Check warningCode scanning / CodeQL Workflow does not contain permissions Medium
Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
Copilot AutofixAI 6 days ago In general, the fix is to explicitly declare a The best minimal fix without changing functionality is to add a top-level Specifically: edit permissions:
contents: readbetween the existing
Suggested changeset
1
.github/workflows/e2e_test.yml
Copilot is powered by AI and may make mistakes. Always verify output.
Refresh and try again.
|
||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| import { useState } from "react"; | ||
| import Card from "./Card"; | ||
| import ClientApi from "@/lib/api/ClientApi"; | ||
| import Avatar from "./Avatar"; | ||
| import Image from "next/image"; | ||
| import { Session } from "inspector/promises"; | ||
| import toast from "react-hot-toast"; | ||
|
|
||
| const api = new ClientApi(); | ||
| export default function EditAvatarModal(props: { | ||
| currentImg: string; | ||
| close: () => void; | ||
| }) { | ||
| const [newAvatar, setNewAvatar] = useState<string>(props.currentImg); | ||
|
|
||
| async function updateAvatar() { | ||
| toast.promise( | ||
| api.changePFP(newAvatar).then(() => location.reload()), | ||
| { | ||
| loading: "Updating profile picture...", | ||
| success: "Successfully updated profile picture!", | ||
| error: "Failed to update profile picture!", | ||
| }, | ||
| ); | ||
| } | ||
|
|
||
| return ( | ||
| <dialog | ||
| open={true} | ||
| className="modal" | ||
| > | ||
| <Card | ||
| title="Edit Avatar" | ||
| coloredTop="bg-secondary" | ||
| > | ||
| <div className="my-9 flex justify-center w-full"> | ||
| <Avatar | ||
| user={{ image: newAvatar }} | ||
| scale="scale-150" | ||
| altText="New Avatar" | ||
| showLevel={false} | ||
| /> | ||
| </div> | ||
|
|
||
| <input | ||
| defaultValue={props.currentImg} | ||
| className="input" | ||
| onChange={(e) => setNewAvatar(e.target.value)} | ||
| placeholder="Enter new avatar url" | ||
| /> | ||
| <div className="flex gap-2 justify-start w-full"> | ||
| <button | ||
| className="btn btn-primary mt-2" | ||
| onClick={updateAvatar} | ||
| > | ||
| Save | ||
| </button> | ||
| <button | ||
| className="btn btn-accent mt-2" | ||
| onClick={props.close} | ||
| > | ||
| Cancel | ||
| </button> | ||
| </div> | ||
| </Card> | ||
| </dialog> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| import { Match, Report } from "@/lib/Types"; | ||
| import Card from "./Card"; | ||
| import { User } from "../lib/Types"; | ||
| import { match } from "assert"; | ||
| import { report } from "process"; | ||
| import Checkbox from "./forms/Checkboxes"; | ||
| import { CheckmarkIcon } from "react-hot-toast"; | ||
| import { useState } from "react"; | ||
| import { toDict } from "@/lib/client/ClientUtils"; | ||
|
|
||
| type MatchData = { | ||
| number: number; | ||
| url: string; | ||
| message: string; | ||
| completed: boolean; | ||
| subjective: boolean; | ||
| }; | ||
|
|
||
| function ViewMatchCard(props: MatchData) { | ||
| return ( | ||
| <Card | ||
| title={"Match " + props.number} | ||
| className="w-full" | ||
| > | ||
| {props.message} | ||
| <a | ||
| href={props.url} | ||
| className={`btn btn-sm ${props.completed ? `btn-ghost` : props.subjective ? `btn-secondary` : `btn-primary`}`} | ||
| > | ||
| {props.completed ? "Submitted" : "Click to scout"} | ||
| </a> | ||
| </Card> | ||
| ); | ||
| } | ||
| export default function ViewMatchesModal(props: { | ||
| close: () => void; | ||
| matches: Match[]; | ||
| reports: Report[]; | ||
| user: User; | ||
| matchPathway: string; | ||
| }) { | ||
| const reportsById = toDict(props.reports); | ||
| const myMatches: MatchData[] = []; | ||
| const [showSubmittedReports, setShowSubmittedReports] = useState(false); | ||
|
|
||
| async function toggleShowSubmittedReports() { | ||
| setShowSubmittedReports(!showSubmittedReports); | ||
| } | ||
|
|
||
| for (const match of props.matches) { | ||
| if (match.subjectiveScouter == props.user._id?.toString()) { | ||
| myMatches.push({ | ||
| number: match.number, | ||
| url: props.matchPathway + `/${match._id}/subjective`, | ||
| message: "You are subjective scouting match " + match.number + ".", | ||
| completed: match.assignedSubjectiveScouterHasSubmitted, | ||
| subjective: true, | ||
| }); | ||
| } | ||
|
|
||
| for (const report of match.reports) { | ||
| if (reportsById[report]?.user == props.user._id?.toString()) { | ||
| myMatches.push({ | ||
| number: match.number, | ||
| url: props.matchPathway + `/${report.toString()}`, | ||
| message: | ||
| "You are scouting team " + | ||
| reportsById[report].robotNumber + | ||
| " in match " + | ||
| match.number + | ||
| ".", | ||
| completed: reportsById[report].submitted, | ||
| subjective: false, | ||
| }); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return ( | ||
| <dialog | ||
| open={true} | ||
| className="modal" | ||
| > | ||
| <Card title="My Matches"> | ||
| <div className="absolute right-2 top-2 flex gap-4 items-center"> | ||
| <div className="flex gap-2"> | ||
| <div>Show Submitted Reports</div> | ||
| <input | ||
| type="checkbox" | ||
| onChange={toggleShowSubmittedReports} | ||
| className="checkbox checkbox-primary" | ||
| /> | ||
| </div> | ||
| <button | ||
| className="btn btn-sm btn-circle btn-ghost " | ||
| onClick={props.close} | ||
| > | ||
| ✕ | ||
| </button> | ||
| </div> | ||
| <div className="overflow-y-scroll h-[650px]"> | ||
| {myMatches | ||
| .filter((matchData) => showSubmittedReports || !matchData.completed) | ||
| .map((matchData, index) => ( | ||
| <ViewMatchCard | ||
| {...matchData} | ||
| key={index} | ||
| /> | ||
| ))} | ||
| </div> | ||
| </Card> | ||
| </dialog> | ||
| ); | ||
| } |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Copilot Autofix
AI 6 days ago
In general, this issue is fixed by explicitly setting the
permissionsfor the GITHUB_TOKEN at the workflow or job level, instead of relying on organization/repository defaults. For test workflows like this one,contents: readis typically sufficient, as the workflow only checks out code and uses artifacts, and does not need to write to the repository, issues, or pull requests.The best fix here, without changing existing functionality, is to add a
permissionsblock at the top level of.github/workflows/e2e_test.yml, just belowname:(or immediately afteron:). This root-levelpermissionsconfiguration will apply to all jobs (e2e_testsandmerge_reports) since neither defines its own permissions. The minimal safe starting point per CodeQL’s suggestion iscontents: read, which allowsactions/checkout@v4to function while avoiding unnecessary write access. No additional imports or methods are needed; only the YAML configuration is updated.Concretely: in
.github/workflows/e2e_test.yml, insert:near the top of the file (e.g., after line 2), keeping indentation aligned with
name:andon:keys.