From 0ca4ba1d48edeb04797d983823909929348fdb7e Mon Sep 17 00:00:00 2001 From: Arkadii Yakovets Date: Mon, 3 Feb 2025 10:47:43 -0800 Subject: [PATCH 01/12] Update labeler config --- .github/labeler.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 9def65b4d..05013de9c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -31,7 +31,7 @@ docker: - 'docker-*.yaml' - '**/Dockerfile.*' -documentation: +docs: - changed-files: - any-glob-to-any-file: - '**/*.md' @@ -67,11 +67,12 @@ nginx: - 'nginx/**' schema: - - changed-files: - - any-glob-to-any-file: - - 'schema/**' - - all-globs-to-all-files: - - '!schema/tests/**' + - all: + - changed-files: + - any-glob-to-any-file: + - 'schema/**' + - all-globs-to-all-files: + - '!schema/tests/**' schema-tests: - changed-files: From 83cb49225d6f5c122b022484dfff1754e612b4bb Mon Sep 17 00:00:00 2001 From: Abhay Date: Tue, 4 Feb 2025 01:52:51 +0530 Subject: [PATCH 02/12] Added license in project schema (#716) * Added license schema in project * pre-commit fix * chnaged license defination and fixed testcases * Update code --------- Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> Co-authored-by: Arkadii Yakovets --- schema/project.json | 21 +++++++++++++++++++ .../negative/license-invalid-value.yaml | 13 ++++++++++++ .../project/positive/optional-properties.yaml | 16 ++++++++++++++ ...ncubator.yaml => required-properties.yaml} | 0 schema/tests/project_test.py | 4 ++++ 5 files changed, 54 insertions(+) create mode 100644 schema/tests/data/project/negative/license-invalid-value.yaml create mode 100644 schema/tests/data/project/positive/optional-properties.yaml rename schema/tests/data/project/positive/{code-incubator.yaml => required-properties.yaml} (100%) diff --git a/schema/project.json b/schema/project.json index d91b92a70..a9b04c128 100644 --- a/schema/project.json +++ b/schema/project.json @@ -62,6 +62,27 @@ "title": "Project level.", "type": "number" }, + "license": { + "description": "The license of the project.", + "enum": [ + "AGPL-3.0", + "Apache-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "CC-BY-4.0", + "CC-BY-SA-4.0", + "CC0-1.0", + "EUPL-1.2", + "GPL-2.0", + "GPL-3.0", + "LGPL-2.1", + "LGPL-3.0", + "MIT", + "MPL-2.0", + "OTHER" + ], + "type": "string" + }, "name": { "description": "The unique name of the project.", "minLength": 10, diff --git a/schema/tests/data/project/negative/license-invalid-value.yaml b/schema/tests/data/project/negative/license-invalid-value.yaml new file mode 100644 index 000000000..ed2fdcb79 --- /dev/null +++ b/schema/tests/data/project/negative/license-invalid-value.yaml @@ -0,0 +1,13 @@ +audience: builder +leaders: + - github: leader-1-github + - github: leader-2-github +level: 2 +license: INVALID-LICENSE-VALUE +name: OWASP Project Invalid License +pitch: A project with invalid license value +tags: + - tag1 + - tag2 + - tag3 +type: code diff --git a/schema/tests/data/project/positive/optional-properties.yaml b/schema/tests/data/project/positive/optional-properties.yaml new file mode 100644 index 000000000..b1950e437 --- /dev/null +++ b/schema/tests/data/project/positive/optional-properties.yaml @@ -0,0 +1,16 @@ +audience: breaker +leaders: + - github: leader-1-github + name: Leader 1 Name + - github: leader-2-github + name: Leader 2 Name + slack: leader-2-slack +level: 2 +license: MIT +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code diff --git a/schema/tests/data/project/positive/code-incubator.yaml b/schema/tests/data/project/positive/required-properties.yaml similarity index 100% rename from schema/tests/data/project/positive/code-incubator.yaml rename to schema/tests/data/project/positive/required-properties.yaml diff --git a/schema/tests/project_test.py b/schema/tests/project_test.py index c688543eb..963013ea6 100644 --- a/schema/tests/project_test.py +++ b/schema/tests/project_test.py @@ -30,6 +30,10 @@ def test_positive(project_schema): ("audience-empty.yaml", "'' is not one of ['breaker', 'builder', 'defender']"), ("audience-missing.yaml", "'audience' is a required property"), ("level-invalid.yaml", "2.5 is not one of [2, 3, 3.5, 4]"), + ( + "license-invalid-value.yaml", + "'INVALID-LICENSE-VALUE' is not one of ['AGPL-3.0', 'Apache-2.0', 'BSD-2-Clause', 'BSD-3-Clause', 'CC-BY-4.0', 'CC-BY-SA-4.0', 'CC0-1.0', 'EUPL-1.2', 'GPL-2.0', 'GPL-3.0', 'LGPL-2.1', 'LGPL-3.0', 'MIT', 'MPL-2.0', 'OTHER']", + ), ("name-empty.yaml", "'' is too short"), ("name-none.yaml", "None is not of type 'string'"), ], From 6247ba61408dcc9ee7dc4204c4ef0074d6c43033 Mon Sep 17 00:00:00 2001 From: Raj gupta <134638667+Rajgupta36@users.noreply.github.com> Date: Tue, 4 Feb 2025 04:31:45 +0530 Subject: [PATCH 03/12] added_git_img_optimization (#733) --- frontend/src/components/ContributorAvatar.tsx | 7 ++++--- frontend/src/components/ToggleContributors.tsx | 2 +- frontend/src/components/UserCard.tsx | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/frontend/src/components/ContributorAvatar.tsx b/frontend/src/components/ContributorAvatar.tsx index 358713208..ff27bb2ed 100644 --- a/frontend/src/components/ContributorAvatar.tsx +++ b/frontend/src/components/ContributorAvatar.tsx @@ -1,8 +1,9 @@ import { Link } from '@chakra-ui/react' +import { memo } from 'react' import { topContributorsType } from 'types/contributor' import { Tooltip } from 'components/ui/tooltip' -const ContributorAvatar = ({ contributor }: { contributor: topContributorsType }) => { +const ContributorAvatar = memo(({ contributor }: { contributor: topContributorsType }) => { const displayName = contributor.name || contributor.login return ( @@ -21,12 +22,12 @@ const ContributorAvatar = ({ contributor }: { contributor: topContributorsType } > {`${displayName}'s ) -} +}) export default ContributorAvatar diff --git a/frontend/src/components/ToggleContributors.tsx b/frontend/src/components/ToggleContributors.tsx index 314aa497f..b24fe3640 100644 --- a/frontend/src/components/ToggleContributors.tsx +++ b/frontend/src/components/ToggleContributors.tsx @@ -31,7 +31,7 @@ const TopContributors = ({ className="flex cursor-pointer items-center space-x-3 rounded-lg p-3 hover:bg-gray-200 dark:hover:bg-gray-700" > {contributor.name diff --git a/frontend/src/components/UserCard.tsx b/frontend/src/components/UserCard.tsx index b4bd08cb3..8aa8ef350 100644 --- a/frontend/src/components/UserCard.tsx +++ b/frontend/src/components/UserCard.tsx @@ -11,7 +11,7 @@ const UserCard = ({ avatar, name, company, button }: UserCardProps) => {
{avatar ? ( - {name} + {name} ) : (
Date: Tue, 4 Feb 2025 04:50:56 +0530 Subject: [PATCH 04/12] Added sponsor definition in Project Schema (#721) * Added sposor defination * pre-commit fix * fixed testcase after audience required property got merged --------- Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> Co-authored-by: Arkadii Yakovets --- schema/project.json | 38 +++++++++++++++++++ .../project/negative/sponsors-empty-list.yaml | 15 ++++++++ .../negative/sponsors-name-missing.yaml | 18 +++++++++ .../negative/sponsors-url-missing.yaml | 18 +++++++++ .../project/positive/required-properties.yaml | 5 +++ schema/tests/project_test.py | 3 ++ 6 files changed, 97 insertions(+) create mode 100644 schema/tests/data/project/negative/sponsors-empty-list.yaml create mode 100644 schema/tests/data/project/negative/sponsors-name-missing.yaml create mode 100644 schema/tests/data/project/negative/sponsors-url-missing.yaml diff --git a/schema/project.json b/schema/project.json index a9b04c128..c502abcee 100644 --- a/schema/project.json +++ b/schema/project.json @@ -24,6 +24,36 @@ } }, "additionalProperties": false + }, + "sponsor": { + "type": "object", + "title": "Sponsor", + "description": "A project sponsor.", + "required": [ + "name", + "url" + ], + "properties": { + "description": { + "type": "string", + "description": "A brief description of the sponsor." + }, + "logo": { + "type": "string", + "description": "The URL of the sponsor's logo.", + "format": "uri" + }, + "name": { + "type": "string", + "description": "The name of the sponsor or organization." + }, + "url": { + "type": "string", + "description": "The URL of the sponsor.", + "format": "uri" + } + }, + "additionalProperties": false } }, @@ -92,6 +122,14 @@ "description": "The project pitch.", "type": "string" }, + "sponsors": { + "description": "Sponsors of the project.", + "type": "array", + "items": { + "$ref": "#/$defs/sponsor" + }, + "minItems": 1 + }, "tags": { "description": "Tags for the project", "type": "array", diff --git a/schema/tests/data/project/negative/sponsors-empty-list.yaml b/schema/tests/data/project/negative/sponsors-empty-list.yaml new file mode 100644 index 000000000..af9e922ef --- /dev/null +++ b/schema/tests/data/project/negative/sponsors-empty-list.yaml @@ -0,0 +1,15 @@ +audience: breaker +leaders: + - github: leader-1-github + name: Leader 1 Name + - github: leader-2-github + name: Leader 2 Name +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code +sponsors: [] diff --git a/schema/tests/data/project/negative/sponsors-name-missing.yaml b/schema/tests/data/project/negative/sponsors-name-missing.yaml new file mode 100644 index 000000000..ba2980fb5 --- /dev/null +++ b/schema/tests/data/project/negative/sponsors-name-missing.yaml @@ -0,0 +1,18 @@ +audience: breaker +leaders: + - github: leader-name-1 + name: Leader Name 1 + - github: leader-name-2 + name: Leader Name 2 +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code +sponsors: + - description: A great sponsor + logo: https://sponsor1.com/logo.png + url: https://sponsor1.com diff --git a/schema/tests/data/project/negative/sponsors-url-missing.yaml b/schema/tests/data/project/negative/sponsors-url-missing.yaml new file mode 100644 index 000000000..3d21bf5af --- /dev/null +++ b/schema/tests/data/project/negative/sponsors-url-missing.yaml @@ -0,0 +1,18 @@ +audience: breaker +leaders: + - github: leader-1-github + name: Leader 1 Name + - github: leader-2-github + name: Leader 2 Name +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code +sponsors: + - description: A great sponsor + logo: https://sponsor1.com/logo.png + name: Sponsor 1 diff --git a/schema/tests/data/project/positive/required-properties.yaml b/schema/tests/data/project/positive/required-properties.yaml index ddc7a5aee..b6bfa0875 100644 --- a/schema/tests/data/project/positive/required-properties.yaml +++ b/schema/tests/data/project/positive/required-properties.yaml @@ -8,6 +8,11 @@ leaders: level: 2 name: OWASP Incubator Code Project pitch: A very brief, one-line description of your project +sponsors: + - description: Sponsor 1 description + logo: https://sponsor1.com/logo.png + name: Sponsor 1 + url: https://sponsor1.com tags: - example-tag-1 - example-tag-2 diff --git a/schema/tests/project_test.py b/schema/tests/project_test.py index 963013ea6..696f66aa1 100644 --- a/schema/tests/project_test.py +++ b/schema/tests/project_test.py @@ -36,6 +36,9 @@ def test_positive(project_schema): ), ("name-empty.yaml", "'' is too short"), ("name-none.yaml", "None is not of type 'string'"), + ("sponsors-empty-list.yaml", "[] should be non-empty"), + ("sponsors-name-missing.yaml", "'name' is a required property"), + ("sponsors-url-missing.yaml", "'url' is a required property"), ], ) def test_negative(project_schema, file_path, error_message): From 55aeed480613799697c8084574047c6ab0a1c843 Mon Sep 17 00:00:00 2001 From: Yash Kumar Shrivastava <142531728+kayashth1@users.noreply.github.com> Date: Tue, 4 Feb 2025 05:14:40 +0530 Subject: [PATCH 05/12] Added demo_url attribute to project schema (#719) * Update .gitignore to exclude venv/ directory * Added demo_url attribute to project schema * Update code --------- Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> Co-authored-by: Arkadii Yakovets --- schema/project.json | 5 +++++ schema/tests/data/project/negative/demo-none.yaml | 15 +++++++++++++++ .../project/positive/optional-properties.yaml | 1 + schema/tests/project_test.py | 1 + 4 files changed, 22 insertions(+) create mode 100644 schema/tests/data/project/negative/demo-none.yaml diff --git a/schema/project.json b/schema/project.json index c502abcee..093311c72 100644 --- a/schema/project.json +++ b/schema/project.json @@ -70,6 +70,11 @@ ], "type": "string" }, + "demo": { + "description": "Optional URL to the project demo.", + "format": "uri", + "type": "string" + }, "leaders": { "description": "Leaders of the project.", "type": "array", diff --git a/schema/tests/data/project/negative/demo-none.yaml b/schema/tests/data/project/negative/demo-none.yaml new file mode 100644 index 000000000..84d033e4c --- /dev/null +++ b/schema/tests/data/project/negative/demo-none.yaml @@ -0,0 +1,15 @@ +audience: breaker +demo: +leaders: + - github: leader-name-1 + name: Leader Name 1 + - github: leader-name-2 + name: Leader Name 2 +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code diff --git a/schema/tests/data/project/positive/optional-properties.yaml b/schema/tests/data/project/positive/optional-properties.yaml index b1950e437..2f9c06e94 100644 --- a/schema/tests/data/project/positive/optional-properties.yaml +++ b/schema/tests/data/project/positive/optional-properties.yaml @@ -1,4 +1,5 @@ audience: breaker +demo: https://some-demo-url.com leaders: - github: leader-1-github name: Leader 1 Name diff --git a/schema/tests/project_test.py b/schema/tests/project_test.py index 696f66aa1..5c3ffedc4 100644 --- a/schema/tests/project_test.py +++ b/schema/tests/project_test.py @@ -29,6 +29,7 @@ def test_positive(project_schema): ), ("audience-empty.yaml", "'' is not one of ['breaker', 'builder', 'defender']"), ("audience-missing.yaml", "'audience' is a required property"), + ("demo-none.yaml", "None is not of type 'string'"), ("level-invalid.yaml", "2.5 is not one of [2, 3, 3.5, 4]"), ( "license-invalid-value.yaml", From d0d7f485f3fabab5028ed8a07747543d6743eb5a Mon Sep 17 00:00:00 2001 From: Raj gupta <134638667+Rajgupta36@users.noreply.github.com> Date: Tue, 4 Feb 2025 05:25:18 +0530 Subject: [PATCH 06/12] added_schema_for_events (#732) * added_schema_for_events * Update code --------- Co-authored-by: Arkadii Yakovets --- schema/project.json | 10 ++++++++++ .../data/project/negative/events-empty.yaml | 16 ++++++++++++++++ .../negative/events-non-unique-urls.yaml | 18 ++++++++++++++++++ .../project/positive/optional-properties.yaml | 3 +++ schema/tests/project_test.py | 5 +++++ 5 files changed, 52 insertions(+) create mode 100644 schema/tests/data/project/negative/events-empty.yaml create mode 100644 schema/tests/data/project/negative/events-non-unique-urls.yaml diff --git a/schema/project.json b/schema/project.json index 093311c72..251577aba 100644 --- a/schema/project.json +++ b/schema/project.json @@ -75,6 +75,16 @@ "format": "uri", "type": "string" }, + "events": { + "description": "Event URLs related to the project.", + "type": "array", + "items": { + "format": "uri", + "type": "string" + }, + "minItems": 1, + "uniqueItems": true + }, "leaders": { "description": "Leaders of the project.", "type": "array", diff --git a/schema/tests/data/project/negative/events-empty.yaml b/schema/tests/data/project/negative/events-empty.yaml new file mode 100644 index 000000000..2786151ee --- /dev/null +++ b/schema/tests/data/project/negative/events-empty.yaml @@ -0,0 +1,16 @@ +audience: breaker +leaders: + - github: leader-1-github + name: Leader 1 Name + - github: leader-2-github + name: Leader 2 Name + slack: leader-2-slack +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code +events: [] diff --git a/schema/tests/data/project/negative/events-non-unique-urls.yaml b/schema/tests/data/project/negative/events-non-unique-urls.yaml new file mode 100644 index 000000000..b50c031e5 --- /dev/null +++ b/schema/tests/data/project/negative/events-non-unique-urls.yaml @@ -0,0 +1,18 @@ +audience: breaker +leaders: + - github: leader-1-github + name: Leader 1 Name + - github: leader-2-github + name: Leader 2 Name + slack: leader-2-slack +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code +events: + - "https://example.com/event1" + - "https://example.com/event1" diff --git a/schema/tests/data/project/positive/optional-properties.yaml b/schema/tests/data/project/positive/optional-properties.yaml index 2f9c06e94..2564739cf 100644 --- a/schema/tests/data/project/positive/optional-properties.yaml +++ b/schema/tests/data/project/positive/optional-properties.yaml @@ -1,5 +1,8 @@ audience: breaker demo: https://some-demo-url.com +events: + - 'https://example.com/event1' + - 'https://example.com/event2' leaders: - github: leader-1-github name: Leader 1 Name diff --git a/schema/tests/project_test.py b/schema/tests/project_test.py index 5c3ffedc4..1ab6f998f 100644 --- a/schema/tests/project_test.py +++ b/schema/tests/project_test.py @@ -30,6 +30,11 @@ def test_positive(project_schema): ("audience-empty.yaml", "'' is not one of ['breaker', 'builder', 'defender']"), ("audience-missing.yaml", "'audience' is a required property"), ("demo-none.yaml", "None is not of type 'string'"), + ("events-empty.yaml", "[] should be non-empty"), + ( + "events-non-unique-urls.yaml", + "['https://example.com/event1', 'https://example.com/event1'] has non-unique elements", + ), ("level-invalid.yaml", "2.5 is not one of [2, 3, 3.5, 4]"), ( "license-invalid-value.yaml", From 5148071985a796d565ed317aa7d250451dc4eed1 Mon Sep 17 00:00:00 2001 From: AbhayTopno <143319154+AbhayTopno@users.noreply.github.com> Date: Tue, 4 Feb 2025 05:57:05 +0530 Subject: [PATCH 07/12] Addition of email to leader structure (#731) * Addition of Contribute Section in Home of Slack NestBot * Update contribute.py * Update of apps/slack/commands/contribute * Minor changes * Update of code after the review * Update backend/apps/slack/commands/contribute.py Co-authored-by: Nitin Awari <99824048+nitinawari@users.noreply.github.com> * Update urls.py * Update contribute.py * Update code * Addition of email to leader structure * Addition of email to leader structure * Addition of email to leader structure * Update vite.config.ts * Update project.json * Update project.json * Update code-incubator.yaml * Update project_test.py * Update email-missing-at.yaml * Update code-incubator.yaml * Update email-invalid-domain.yaml * Update email-invalid.yaml * Update code * Revert unrelated changes --------- Co-authored-by: Nitin Awari <99824048+nitinawari@users.noreply.github.com> Co-authored-by: Arkadii Yakovets Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> --- schema/project.json | 5 +++++ .../data/project/negative/leader-email-empty.yaml | 13 +++++++++++++ .../data/project/negative/leader-email-missing.yaml | 13 +++++++++++++ schema/tests/project_test.py | 8 ++++++++ 4 files changed, 39 insertions(+) create mode 100644 schema/tests/data/project/negative/leader-email-empty.yaml create mode 100644 schema/tests/data/project/negative/leader-email-missing.yaml diff --git a/schema/project.json b/schema/project.json index 251577aba..5cf633edd 100644 --- a/schema/project.json +++ b/schema/project.json @@ -8,6 +8,11 @@ "description": "A project leader.", "required": ["github"], "properties": { + "email": { + "description": "The leader's email address.", + "format": "email", + "type": ["string", "null"] + }, "github": { "type": "string", "description": "The GitHub username.", diff --git a/schema/tests/data/project/negative/leader-email-empty.yaml b/schema/tests/data/project/negative/leader-email-empty.yaml new file mode 100644 index 000000000..0648221be --- /dev/null +++ b/schema/tests/data/project/negative/leader-email-empty.yaml @@ -0,0 +1,13 @@ +audience: breaker +leaders: + - email: '' + github: leader-1-github + name: Leader 1 Name +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code diff --git a/schema/tests/data/project/negative/leader-email-missing.yaml b/schema/tests/data/project/negative/leader-email-missing.yaml new file mode 100644 index 000000000..b7918eb30 --- /dev/null +++ b/schema/tests/data/project/negative/leader-email-missing.yaml @@ -0,0 +1,13 @@ +audience: breaker +leaders: + - email: + github: leader-1-github + name: Leader 1 Name +level: 2 +name: OWASP Incubator Code Project +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code diff --git a/schema/tests/project_test.py b/schema/tests/project_test.py index 1ab6f998f..7310b86e7 100644 --- a/schema/tests/project_test.py +++ b/schema/tests/project_test.py @@ -35,6 +35,14 @@ def test_positive(project_schema): "events-non-unique-urls.yaml", "['https://example.com/event1', 'https://example.com/event1'] has non-unique elements", ), + ( + "leader-email-empty.yaml", + "[{'email': '', 'github': 'leader-1-github', 'name': 'Leader 1 Name'}] is too short", + ), + ( + "leader-email-missing.yaml", + "[{'email': None, 'github': 'leader-1-github', 'name': 'Leader 1 Name'}] is too short", + ), ("level-invalid.yaml", "2.5 is not one of [2, 3, 3.5, 4]"), ( "license-invalid-value.yaml", From 039c87b52cd96db66d75057ec4faeae0bfe97527 Mon Sep 17 00:00:00 2001 From: yashgoyal0110 <149111979+yashgoyal0110@users.noreply.github.com> Date: Tue, 4 Feb 2025 06:11:17 +0530 Subject: [PATCH 08/12] download attribute in project schema (#713) * download attribute * download att * test cases * alphbatical order * Update code --------- Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> Co-authored-by: Arkadii Yakovets --- schema/project.json | 11 +++++++++++ .../data/project/negative/downloads-empty.yaml | 13 +++++++++++++ .../project/negative/downloads-non-unique.yaml | 15 +++++++++++++++ .../project/positive/optional-properties.yaml | 3 +++ schema/tests/project_test.py | 5 +++++ 5 files changed, 47 insertions(+) create mode 100644 schema/tests/data/project/negative/downloads-empty.yaml create mode 100644 schema/tests/data/project/negative/downloads-non-unique.yaml diff --git a/schema/project.json b/schema/project.json index 5cf633edd..c8a9e2bc0 100644 --- a/schema/project.json +++ b/schema/project.json @@ -80,6 +80,17 @@ "format": "uri", "type": "string" }, + "downloads": { + "description": "Optional list of download URLs.", + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "minItems": 1, + "uniqueItems": true, + "optional": true + }, "events": { "description": "Event URLs related to the project.", "type": "array", diff --git a/schema/tests/data/project/negative/downloads-empty.yaml b/schema/tests/data/project/negative/downloads-empty.yaml new file mode 100644 index 000000000..ee7eb3b3c --- /dev/null +++ b/schema/tests/data/project/negative/downloads-empty.yaml @@ -0,0 +1,13 @@ +audience: builder +downloads: [] +name: "Test Project" +level: 3 +leaders: + - github: "testuser1" + - github: "testuser2" +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code diff --git a/schema/tests/data/project/negative/downloads-non-unique.yaml b/schema/tests/data/project/negative/downloads-non-unique.yaml new file mode 100644 index 000000000..3f1f87e11 --- /dev/null +++ b/schema/tests/data/project/negative/downloads-non-unique.yaml @@ -0,0 +1,15 @@ +audience: builder +downloads: + - https://abc.com/download + - https://abc.com/download +name: "Test Project" +level: 3 +leaders: + - github: "testuser1" + - github: "testuser2" +pitch: A very brief, one-line description of your project +tags: + - example-tag-1 + - example-tag-2 + - example-tag-3 +type: code diff --git a/schema/tests/data/project/positive/optional-properties.yaml b/schema/tests/data/project/positive/optional-properties.yaml index 2564739cf..51f13ac55 100644 --- a/schema/tests/data/project/positive/optional-properties.yaml +++ b/schema/tests/data/project/positive/optional-properties.yaml @@ -1,5 +1,8 @@ audience: breaker demo: https://some-demo-url.com +downloads: + - https://abc.com/download1 + - https://abc.com/download2 events: - 'https://example.com/event1' - 'https://example.com/event2' diff --git a/schema/tests/project_test.py b/schema/tests/project_test.py index 7310b86e7..cd96de8c2 100644 --- a/schema/tests/project_test.py +++ b/schema/tests/project_test.py @@ -30,6 +30,11 @@ def test_positive(project_schema): ("audience-empty.yaml", "'' is not one of ['breaker', 'builder', 'defender']"), ("audience-missing.yaml", "'audience' is a required property"), ("demo-none.yaml", "None is not of type 'string'"), + ("downloads-empty.yaml", "[] should be non-empty"), + ( + "downloads-non-unique.yaml", + "['https://abc.com/download', 'https://abc.com/download'] has non-unique elements", + ), ("events-empty.yaml", "[] should be non-empty"), ( "events-non-unique-urls.yaml", From bb820b1d6401969741819ce5bfc8cf886a8e480b Mon Sep 17 00:00:00 2001 From: Abhay Date: Tue, 4 Feb 2025 07:36:02 +0530 Subject: [PATCH 09/12] Added related repository block in the Project Details (#722) * Added related reposiotry block in the Project Details * Added testcase and fixed testcases * Update code * fixed transition --------- Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> Co-authored-by: Arkadii Yakovets --- .../apps/github/graphql/nodes/repository.py | 27 ++++++ backend/apps/github/models/repository.py | 5 ++ backend/apps/owasp/graphql/nodes/project.py | 6 ++ .../github/graphql/nodes/repository_test.py | 33 +++++++ .../tests/owasp/graphql/nodes/project_test.py | 2 +- frontend/src/api/queries/projectQueries.ts | 9 ++ frontend/src/components/CardDetailsPage.tsx | 11 ++- frontend/src/components/RepositoriesCard.tsx | 88 +++++++++++++++++++ frontend/src/pages/ProjectDetails.tsx | 5 +- frontend/src/types/card.ts | 8 +- frontend/src/types/project.ts | 14 +++ 11 files changed, 203 insertions(+), 5 deletions(-) create mode 100644 backend/apps/github/graphql/nodes/repository.py create mode 100644 backend/tests/github/graphql/nodes/repository_test.py create mode 100644 frontend/src/components/RepositoriesCard.tsx diff --git a/backend/apps/github/graphql/nodes/repository.py b/backend/apps/github/graphql/nodes/repository.py new file mode 100644 index 000000000..f8d4e70f1 --- /dev/null +++ b/backend/apps/github/graphql/nodes/repository.py @@ -0,0 +1,27 @@ +"""GitHub repository GraphQL node.""" + +import graphene + +from apps.common.graphql.nodes import BaseNode +from apps.github.models.repository import Repository + + +class RepositoryNode(BaseNode): + """GitHub repository node.""" + + url = graphene.String() + + class Meta: + model = Repository + fields = ( + "name", + "forks_count", + "stars_count", + "open_issues_count", + "subscribers_count", + "contributors_count", + ) + + def resolve_url(self, info): + """Resolve URL.""" + return self.url diff --git a/backend/apps/github/models/repository.py b/backend/apps/github/models/repository.py index fecbb70ea..62208161b 100644 --- a/backend/apps/github/models/repository.py +++ b/backend/apps/github/models/repository.py @@ -135,6 +135,11 @@ def top_languages(self): if v >= LANGUAGE_PERCENTAGE_THRESHOLD and k.lower() not in IGNORED_LANGUAGES ) + @property + def url(self): + """Return repository URL.""" + return f"https://github.com/{self.path}" + def from_github( self, gh_repository, diff --git a/backend/apps/owasp/graphql/nodes/project.py b/backend/apps/owasp/graphql/nodes/project.py index 33834e756..29000dc79 100644 --- a/backend/apps/owasp/graphql/nodes/project.py +++ b/backend/apps/owasp/graphql/nodes/project.py @@ -5,6 +5,7 @@ from apps.common.graphql.nodes import BaseNode from apps.github.graphql.nodes.issue import IssueNode from apps.github.graphql.nodes.release import ReleaseNode +from apps.github.graphql.nodes.repository import RepositoryNode from apps.owasp.models.project import Project RECENT_ISSUES_LIMIT = 10 @@ -16,6 +17,7 @@ class ProjectNode(BaseNode): recent_issues = graphene.List(IssueNode) recent_releases = graphene.List(ReleaseNode) + repositories = graphene.List(RepositoryNode) class Meta: model = Project @@ -28,3 +30,7 @@ def resolve_recent_issues(self, info): def resolve_recent_releases(self, info): """Resolve project recent releases.""" return self.published_releases.order_by("-published_at")[:RECENT_RELEASES_LIMIT] + + def resolve_repositories(self, info): + """Resolve repositories.""" + return self.repositories.order_by("-pushed_at", "-updated_at") diff --git a/backend/tests/github/graphql/nodes/repository_test.py b/backend/tests/github/graphql/nodes/repository_test.py new file mode 100644 index 000000000..b92e93939 --- /dev/null +++ b/backend/tests/github/graphql/nodes/repository_test.py @@ -0,0 +1,33 @@ +"""Test cases for RepositoryNode.""" + +from apps.common.graphql.nodes import BaseNode +from apps.github.graphql.nodes.repository import RepositoryNode +from apps.github.models.repository import Repository + + +class TestRepositoryNode: + """Test cases for RepositoryNode class.""" + + def test_repository_node_inheritance(self): + """Test if RepositoryNode inherits from BaseNode.""" + assert issubclass(RepositoryNode, BaseNode) + + def test_meta_configuration(self): + """Test if Meta is properly configured.""" + assert RepositoryNode._meta.model == Repository + expected_fields = { + "contributors_count", + "forks_count", + "name", + "open_issues_count", + "stars_count", + "subscribers_count", + "url", + } + assert set(RepositoryNode._meta.fields) == expected_fields + + def test_resolve_url_field(self, mocker): + """Test if URL field is properly defined.""" + field = RepositoryNode._meta.fields.get("url") + assert field is not None + assert str(field.type) == "String" diff --git a/backend/tests/owasp/graphql/nodes/project_test.py b/backend/tests/owasp/graphql/nodes/project_test.py index 6d11a7e36..22040ea6a 100644 --- a/backend/tests/owasp/graphql/nodes/project_test.py +++ b/backend/tests/owasp/graphql/nodes/project_test.py @@ -94,7 +94,7 @@ def test_all_fields_exist_in_model(self): model_fields = {f.name for f in Project._meta.get_fields()} node_fields = set(ProjectNode._meta.fields.keys()) - custom_fields = {"recent_issues", "recent_releases", "nest_url"} + custom_fields = {"recent_issues", "recent_releases", "repositories", "nest_url"} node_fields = node_fields - custom_fields assert all(field in model_fields for field in node_fields) diff --git a/frontend/src/api/queries/projectQueries.ts b/frontend/src/api/queries/projectQueries.ts index 4cd753a3b..ef5ef7aa2 100644 --- a/frontend/src/api/queries/projectQueries.ts +++ b/frontend/src/api/queries/projectQueries.ts @@ -22,6 +22,15 @@ export const GET_PROJECT_DATA = gql` name } } + repositories { + contributorsCount + forksCount + name + openIssuesCount + url + starsCount + subscribersCount + } } } ` diff --git a/frontend/src/components/CardDetailsPage.tsx b/frontend/src/components/CardDetailsPage.tsx index 09d9e020b..6ae1b081a 100644 --- a/frontend/src/components/CardDetailsPage.tsx +++ b/frontend/src/components/CardDetailsPage.tsx @@ -6,7 +6,7 @@ import { faCalendar, faFileCode, faTag, - faBook, + faExclamationCircle, } from '@fortawesome/free-solid-svg-icons' import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { DetailsCardProps } from 'types/card' @@ -15,6 +15,7 @@ import { getSocialIcon } from 'utils/urlIconMappings' import ChapterMap from 'components/ChapterMap' import InfoBlock from 'components/InfoBlock' import ItemCardList from 'components/ItemCardList' +import RepositoriesCard from 'components/RepositoriesCard' import SecondaryCard from 'components/SecondaryCard' import TopContributors from 'components/ToggleContributors' import ToggleableList from 'components/ToogleList' @@ -34,6 +35,7 @@ const DetailsCard = ({ recentIssues, recentReleases, geolocationData = null, + repositories = [], }: DetailsCardProps) => { return (
@@ -84,7 +86,7 @@ const DetailsCard = ({ /> @@ -136,6 +138,11 @@ const DetailsCard = ({ /> )} + {type === 'project' && repositories.length > 0 && ( + + + + )}
) diff --git a/frontend/src/components/RepositoriesCard.tsx b/frontend/src/components/RepositoriesCard.tsx new file mode 100644 index 000000000..a621aeb71 --- /dev/null +++ b/frontend/src/components/RepositoriesCard.tsx @@ -0,0 +1,88 @@ +import { + faCodeFork, + faStar, + faUsers, + faExclamationCircle, + faChevronDown, + faChevronUp, + IconDefinition, +} from '@fortawesome/free-solid-svg-icons' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import type React from 'react' +import { useState } from 'react' +import { RepositoriesCardProps, RepositoryCardProps } from 'types/project' + +const RepositoriesCard: React.FC = ({ repositories }) => { + const [showAllRepositories, setShowAllRepositories] = useState(false) + + const displayedRepositories = showAllRepositories ? repositories : repositories.slice(0, 4) + + return ( +
+
+ {displayedRepositories.map((repo, index) => ( + + ))} +
+ {repositories.length > 4 && ( +
+ +
+ )} +
+ ) +} + +const RepositoryItem: React.FC = ({ + name, + openIssuesCount, + contributorsCount, + forksCount, + starsCount, + url, +}) => ( +
+ + {name} + +
+ + + + +
+
+) + +const InfoItem: React.FC<{ icon: IconDefinition; label: string; value: number }> = ({ + icon, + label, + value, +}) => ( +
+ + + {label} + + {value.toLocaleString()} +
+) + +export default RepositoriesCard diff --git a/frontend/src/pages/ProjectDetails.tsx b/frontend/src/pages/ProjectDetails.tsx index f03b66a62..3ed6c6df1 100644 --- a/frontend/src/pages/ProjectDetails.tsx +++ b/frontend/src/pages/ProjectDetails.tsx @@ -16,6 +16,7 @@ const ProjectDetailsPage = () => { const [isLoading, setIsLoading] = useState(true) const [recentReleases, setRecentReleases] = useState([]) const [recentIssues, setRecentIssues] = useState([]) + const [repositories, setRepositories] = useState([]) const { data, @@ -41,7 +42,8 @@ const ProjectDetailsPage = () => { useEffect(() => { if (data) { setRecentReleases(data?.project?.recentReleases || []) - setRecentIssues(data?.project?.recentIssues) + setRecentIssues(data?.project?.recentIssues || []) + setRepositories(data?.project?.repositories || []) } if (graphQLRequestError && !isLoading) { toast({ @@ -103,6 +105,7 @@ const ProjectDetailsPage = () => { topics={project.topics} recentReleases={recentReleases} recentIssues={recentIssues} + repositories={repositories} /> ) } diff --git a/frontend/src/types/card.ts b/frontend/src/types/card.ts index 1a90f7731..819010c11 100644 --- a/frontend/src/types/card.ts +++ b/frontend/src/types/card.ts @@ -4,7 +4,12 @@ import { ChapterType } from './chapter' import { topContributorsType } from './contributor' import { IconType } from './icon' import { Level } from './level' -import { ProjectIssuesType, ProjectReleaseType, ProjectStatsType } from './project' +import { + ProjectIssuesType, + ProjectReleaseType, + ProjectStatsType, + RepositoryCardProps, +} from './project' export interface UserCardProps { avatar: string @@ -43,4 +48,5 @@ export interface DetailsCardProps { type: string recentIssues?: ProjectIssuesType[] recentReleases?: ProjectReleaseType[] + repositories?: RepositoryCardProps[] } diff --git a/frontend/src/types/project.ts b/frontend/src/types/project.ts index bf2f34548..f894a5e0d 100644 --- a/frontend/src/types/project.ts +++ b/frontend/src/types/project.ts @@ -60,3 +60,17 @@ export type ProjectReleaseType = { } tag_name: string } + +export type RepositoryCardProps = { + contributorsCount: number + forksCount: number + name: string + openIssuesCount: number + starsCount: number + subscribersCount: number + url: string +} + +export interface RepositoriesCardProps { + repositories: RepositoryCardProps[] +} From 3f051769eda7e40662ffde167d42fa6a6dc87853 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:15:20 -0800 Subject: [PATCH 10/12] Bump @chakra-ui/react from 3.5.1 to 3.6.0 in /frontend (#726) Bumps [@chakra-ui/react](https://github.com/chakra-ui/chakra-ui/tree/HEAD/packages/react) from 3.5.1 to 3.6.0. - [Release notes](https://github.com/chakra-ui/chakra-ui/releases) - [Changelog](https://github.com/chakra-ui/chakra-ui/blob/main/packages/react/CHANGELOG.md) - [Commits](https://github.com/chakra-ui/chakra-ui/commits/@chakra-ui/react@3.6.0/packages/react) --- updated-dependencies: - dependency-name: "@chakra-ui/react" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Arkadii Yakovets <2201626+arkid15r@users.noreply.github.com> --- frontend/package-lock.json | 8 ++++---- frontend/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b5de1154b..11de777a7 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,7 +13,7 @@ "@algolia/autocomplete-theme-classic": "^1.17.9", "@apollo/client": "^3.12.7", "@ark-ui/react": "^4.9.1", - "@chakra-ui/react": "^3.4.0", + "@chakra-ui/react": "^3.6.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@fortawesome/fontawesome-svg-core": "^6.7.0", @@ -1038,9 +1038,9 @@ "license": "MIT" }, "node_modules/@chakra-ui/react": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.5.1.tgz", - "integrity": "sha512-RwhFNwhmlAgDOUBLqwKGvhra57Ts65hO/frcCpiLmROc4xDNGiybN7Cq90bft2PztlWBZk7ixpLkiMQsrGXlmQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@chakra-ui/react/-/react-3.6.0.tgz", + "integrity": "sha512-gCFNr99xmhaXxLmqXxj4ppJand0ltgnohwhIPjV3mzOz4EOJPGhDQAJ2BAtvMKiY9XS/OYBsuIt6jfEwmOdSGA==", "license": "MIT", "dependencies": { "@ark-ui/react": "4.9.1", diff --git a/frontend/package.json b/frontend/package.json index 4287eb810..a7c34dd8d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -23,7 +23,7 @@ "@algolia/autocomplete-theme-classic": "^1.17.9", "@apollo/client": "^3.12.7", "@ark-ui/react": "^4.9.1", - "@chakra-ui/react": "^3.4.0", + "@chakra-ui/react": "^3.6.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", "@fortawesome/fontawesome-svg-core": "^6.7.0", From 518677f56b640b4045bd6a2032a85d7327ec198d Mon Sep 17 00:00:00 2001 From: Arkadii Yakovets Date: Mon, 3 Feb 2025 22:17:27 -0800 Subject: [PATCH 11/12] Update NestBot commands --- backend/apps/slack/common/gsoc.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backend/apps/slack/common/gsoc.py b/backend/apps/slack/common/gsoc.py index a601b0f59..4401f611b 100644 --- a/backend/apps/slack/common/gsoc.py +++ b/backend/apps/slack/common/gsoc.py @@ -64,11 +64,6 @@ ), divider(), markdown( - "We're building with modern frameworks and tools: *TypeScript, React, Chakra UI, " - f"Tailwind CSS, Python, Django, Docker, and Kubernetes*.{2*NL}" - "OWASP Nest has clean and well-documented code, automated CI/CD pipeline, great test " - "coverage for both the frontend and backend making the project reliable and easy " - f"to scale.{2*NL}" f"Join the effort at <{OWASP_PROJECT_NEST_CHANNEL_ID}|project-nest> and help shape " "the future :rocket:" ), From 63815c9084412beae8d34e81dca1906e34330157 Mon Sep 17 00:00:00 2001 From: Arkadii Yakovets Date: Mon, 3 Feb 2025 22:17:54 -0800 Subject: [PATCH 12/12] Update BE dependencies --- backend/poetry.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/poetry.lock b/backend/poetry.lock index 2b5b41234..083082275 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -242,18 +242,18 @@ tests-mypy = ["mypy (>=1.11.1)", "pytest-mypy-plugins"] [[package]] name = "boto3" -version = "1.36.11" +version = "1.36.12" description = "The AWS SDK for Python" optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "boto3-1.36.11-py3-none-any.whl", hash = "sha256:641dd772eac111d9443258f0f5491c57c2af47bddae94a8d32de19edb5bf7b1c"}, - {file = "boto3-1.36.11.tar.gz", hash = "sha256:b40fbf2c0f22e55b67df95475a68bb72be5169097180a875726b6b884339ac8b"}, + {file = "boto3-1.36.12-py3-none-any.whl", hash = "sha256:32cdf0967287f3ec25a9dc09df0d29cb86b8900c3e0546a63d672775d8127abf"}, + {file = "boto3-1.36.12.tar.gz", hash = "sha256:287d84f49bba3255a17b374578127d42b6251e72f55914a62e0ad9ca78c0954b"}, ] [package.dependencies] -botocore = ">=1.36.11,<1.37.0" +botocore = ">=1.36.12,<1.37.0" jmespath = ">=0.7.1,<2.0.0" s3transfer = ">=0.11.0,<0.12.0" @@ -262,14 +262,14 @@ crt = ["botocore[crt] (>=1.21.0,<2.0a0)"] [[package]] name = "botocore" -version = "1.36.11" +version = "1.36.12" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" groups = ["main"] files = [ - {file = "botocore-1.36.11-py3-none-any.whl", hash = "sha256:82c5660027f696608d0e55feb08c146c11c7ebeba7615961c7765dcf6009a00d"}, - {file = "botocore-1.36.11.tar.gz", hash = "sha256:c919be883f95b9e0c3021429a365d40cd7944b8345a07af30dc8d891ceefe07a"}, + {file = "botocore-1.36.12-py3-none-any.whl", hash = "sha256:5ae1ed362c8ed908a6ced8cdd12b21e2196c100bc79f9e95c9c1fc7f9ea74f5a"}, + {file = "botocore-1.36.12.tar.gz", hash = "sha256:86ed88beb4f244c96529435c868d3940073c2774116f0023fb7691f6e7053bd9"}, ] [package.dependencies]