diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 588b8b753a..380eb49518 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,10 +1,5 @@
name: Server Tests
on:
- push:
- branches:
- - main
- - develop
- - main-hotfix
pull_request: {}
permissions:
@@ -97,22 +92,3 @@ jobs:
uses: actions/upload-artifact@v4
with:
path: /home/runner/frappe-bench/sites/coverage.xml
-
- coverage:
- name: Coverage Wrap Up
- needs: tests
- runs-on: ubuntu-latest
- steps:
- - name: Clone
- uses: actions/checkout@v5
-
- - name: Download artifacts
- uses: actions/download-artifact@v4
-
- - name: Upload coverage data
- uses: codecov/codecov-action@v5
- with:
- name: Server
- token: ${{ secrets.CODECOV_TOKEN }}
- fail_ci_if_error: true
- verbose: true
diff --git a/.github/workflows/generate-pot-file.yml b/.github/workflows/generate-pot-file.yml
deleted file mode 100644
index 6647cf1909..0000000000
--- a/.github/workflows/generate-pot-file.yml
+++ /dev/null
@@ -1,40 +0,0 @@
-name: Regenerate POT file (translatable strings)
-on:
- schedule:
- - cron: "00 16 * * 5"
- workflow_dispatch:
-
-jobs:
- regenerate-pot-file:
- name: Release
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- branch: ["develop"]
- permissions:
- contents: write
- pull-requests: write
-
- steps:
- - name: Checkout
- uses: actions/checkout@v5
- with:
- ref: ${{ matrix.branch }}
-
- - name: Setup Python
- uses: actions/setup-python@v6
- with:
- python-version: "3.14"
-
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- node-version: 24
-
- - name: Run script to update POT file
- run: |
- bash ${GITHUB_WORKSPACE}/.github/helper/update_pot_file.sh
- env:
- GH_TOKEN: ${{ github.token }}
- BASE_BRANCH: ${{ matrix.branch }}
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml
index a801daf51d..daedfc23d7 100644
--- a/.github/workflows/linters.yml
+++ b/.github/workflows/linters.yml
@@ -2,18 +2,14 @@ name: Linters
on:
pull_request:
- workflow_dispatch:
- push:
- branches: [ main ]
permissions:
contents: read
jobs:
linters:
- name: Semgrep Rules
+ name: Pre-commit and Semgrep
runs-on: ubuntu-latest
- if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v5
diff --git a/.github/workflows/make_release_pr.yml b/.github/workflows/make_release_pr.yml
deleted file mode 100644
index 47f065d8b8..0000000000
--- a/.github/workflows/make_release_pr.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-name: Create weekly release
-on:
- schedule:
- - cron: '30 3 * * 3'
- workflow_dispatch:
-
-permissions:
- contents: read
- pull-requests: write
-
-jobs:
- release:
- name: Release
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
-
- steps:
- - uses: octokit/request-action@v2.x
- with:
- route: POST /repos/{owner}/{repo}/pulls
- owner: frappe
- repo: lms
- title: |-
- "chore: merge 'main-hotfix' into 'main'"
- body: "Automated weekly release"
- base: main
- head: main-hotfix
- env:
- GITHUB_TOKEN: ${{ github.token }}
diff --git a/.github/workflows/on_release.yml b/.github/workflows/on_release.yml
deleted file mode 100644
index f6f09319d4..0000000000
--- a/.github/workflows/on_release.yml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Generate Semantic Release
-on:
- workflow_dispatch:
- push:
- branches:
- - main
-
-permissions:
- contents: write
- issues: write
- pull-requests: write
-
-jobs:
- release:
- name: Release
- runs-on: ubuntu-latest
- steps:
- - name: Checkout Entire Repository
- uses: actions/checkout@v5
- with:
- fetch-depth: 0
- persist-credentials: false
- - name: Setup Node.js
- uses: actions/setup-node@v6
- with:
- node-version: 24
- - name: Setup dependencies
- run: |
- npm install @semantic-release/git @semantic-release/exec --no-save
- - name: Create Release
- env:
- GH_TOKEN: ${{ github.token }}
- GITHUB_TOKEN: ${{ github.token }}
- GIT_AUTHOR_NAME: "Frappe PR Bot"
- GIT_AUTHOR_EMAIL: "developers@frappe.io"
- GIT_COMMITTER_NAME: "Frappe PR Bot"
- GIT_COMMITTER_EMAIL: "developers@frappe.io"
- run: npx semantic-release
diff --git a/.github/workflows/semantic.yml b/.github/workflows/semantic.yml
deleted file mode 100644
index 5a04c847f7..0000000000
--- a/.github/workflows/semantic.yml
+++ /dev/null
@@ -1,22 +0,0 @@
-name: Semantic Pull Request
-
-on:
- push:
- branches: [ main ]
- pull_request: {}
-
-permissions:
- contents: read
-
-jobs:
- # This workflow contains a single job called "build"
- semantic:
- name: Validate PR title
- runs-on: ubuntu-latest
-
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v5
-
- - uses: zeke/semantic-pull-requests@main
diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml
index be09f122aa..fc0bc45c48 100644
--- a/.github/workflows/ui-tests.yml
+++ b/.github/workflows/ui-tests.yml
@@ -1,13 +1,7 @@
name: UI Tests
on:
- pull_request:
workflow_dispatch:
- push:
- branches:
- - main
- - develop
- - main-hotfix
permissions:
contents: read
diff --git a/frontend/components.d.ts b/frontend/components.d.ts
index 727e4ac56d..deb9785d71 100644
--- a/frontend/components.d.ts
+++ b/frontend/components.d.ts
@@ -41,6 +41,7 @@ declare module 'vue' {
Coupons: typeof import('./src/components/Settings/Coupons/Coupons.vue')['default']
CourseCard: typeof import('./src/components/CourseCard.vue')['default']
CourseCardOverlay: typeof import('./src/components/CourseCardOverlay.vue')['default']
+ CourseFinalExam: typeof import('./src/components/CourseFinalExam.vue')['default']
CourseInstructors: typeof import('./src/components/CourseInstructors.vue')['default']
CourseOutline: typeof import('./src/components/CourseOutline.vue')['default']
CourseReviews: typeof import('./src/components/CourseReviews.vue')['default']
@@ -60,6 +61,7 @@ declare module 'vue' {
EvaluationModal: typeof import('./src/components/Modals/EvaluationModal.vue')['default']
Evaluators: typeof import('./src/components/Settings/Evaluators.vue')['default']
Event: typeof import('./src/components/Modals/Event.vue')['default']
+ Exam: typeof import('./src/components/Exam.vue')['default']
ExplanationVideos: typeof import('./src/components/Modals/ExplanationVideos.vue')['default']
FeedbackModal: typeof import('./src/components/Modals/FeedbackModal.vue')['default']
FrappeCloudIcon: typeof import('./src/components/Icons/FrappeCloudIcon.vue')['default']
diff --git a/frontend/src/components/AssessmentPlugin.vue b/frontend/src/components/AssessmentPlugin.vue
index a4256a1ca9..43e76eeff1 100644
--- a/frontend/src/components/AssessmentPlugin.vue
+++ b/frontend/src/components/AssessmentPlugin.vue
@@ -123,10 +123,10 @@ const addAssessment = () => {
props.type == 'quiz'
? quiz.value
: props.type == 'dragDrop'
- ? dragDrop.value
- : props.type == 'wordHunt'
- ? wordHunt.value
- : assignment.value
+ ? dragDrop.value
+ : props.type == 'wordHunt'
+ ? wordHunt.value
+ : assignment.value
)
show.value = false
}
diff --git a/frontend/src/components/CertificationLinks.vue b/frontend/src/components/CertificationLinks.vue
index 1f371def6b..4571c9ed4f 100644
--- a/frontend/src/components/CertificationLinks.vue
+++ b/frontend/src/components/CertificationLinks.vue
@@ -14,7 +14,8 @@
certification.data &&
certification.data.membership &&
certification.data.paid_certificate &&
- user.data?.is_student
+ user.data?.is_student &&
+ (!certification.data.final_exam || certification.data.final_exam.passed)
"
>