Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/develop' into fix-talkback-read
Browse files Browse the repository at this point in the history
  • Loading branch information
subhajitxyz committed Oct 12, 2024
2 parents 8d0328c + eb16e59 commit 16230b7
Show file tree
Hide file tree
Showing 11 changed files with 358 additions and 18 deletions.
27 changes: 26 additions & 1 deletion .github/workflows/wiki.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,45 @@
name: Deploy to Wiki
on:
pull_request:
paths:
- 'wiki/**'
push:
branches:
- develop
paths:
- 'wiki/**'
# Triggers this workflow when the wiki is changed
# Triggers this workflow when the wiki is changed.
# (see https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#gollum).
gollum:

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

jobs:
table_of_contents_check:
# To verify that the wiki's table of contents matches the headers accurately.
name: Check Wiki Table of Contents
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2

- name: Set up Bazel
uses: abhinavsingh/setup-bazel@v3
with:
version: 6.5.0

- name: Check Wiki Table of Contents
id: checkWikiToc
run: |
bazel run //scripts:wiki_table_of_contents_check -- ${GITHUB_WORKSPACE}
wiki-deploy:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04]
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/develop' }}
steps:
- uses: actions/checkout@v3
with:
Expand Down
9 changes: 9 additions & 0 deletions scripts/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,15 @@ kt_jvm_binary(
],
)

kt_jvm_binary(
name = "wiki_table_of_contents_check",
testonly = True,
main_class = "org.oppia.android.scripts.wiki.WikiTableOfContentsCheckKt",
runtime_deps = [
"//scripts/src/java/org/oppia/android/scripts/wiki:wiki_table_of_contents_check_lib",
],
)

kt_jvm_binary(
name = "run_coverage",
testonly = True,
Expand Down
18 changes: 18 additions & 0 deletions scripts/src/java/org/oppia/android/scripts/wiki/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
Libraries corresponding to scripting tools that help with continuous integration workflows.
"""

load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library")

kt_jvm_library(
name = "wiki_table_of_contents_check_lib",
testonly = True,
srcs = [
"WikiTableOfContentsCheck.kt",
],
visibility = ["//scripts:oppia_script_binary_visibility"],
deps = [
"//scripts/src/java/org/oppia/android/scripts/common:bazel_client",
"//scripts/src/java/org/oppia/android/scripts/common:git_client",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.oppia.android.scripts.wiki

import java.io.File

/**
* Script for ensuring that the table of contents in each wiki page matches with its respective headers.
*
* Usage:
* bazel run //scripts:wiki_table_of_contents_check -- <path_to_default_working_directory>
*
* Arguments:
* - path_to_default_working_directory: The default working directory on the runner for steps, and the default location of repository.
*
* Example:
* bazel run //scripts:wiki_table_of_contents_check -- $(pwd)
*/
fun main(vararg args: String) {
// Path to the repo's wiki.
val wikiDirPath = "${args[0]}/wiki/"
val wikiDir = File(wikiDirPath)

// Check if the wiki directory exists.
if (wikiDir.exists() && wikiDir.isDirectory) {
processWikiDirectory(wikiDir)
println("WIKI TABLE OF CONTENTS CHECK PASSED")
} else {
println("No contents found in the Wiki directory.")
}
}

private fun processWikiDirectory(wikiDir: File) {
wikiDir.listFiles()?.forEach { file ->
checkTableOfContents(file)
}
}

private fun checkTableOfContents(file: File) {
val fileContents = file.readLines()
val tocStartIdx = fileContents.indexOfFirst {
it.contains(Regex("""##\s+Table\s+of\s+Contents""", RegexOption.IGNORE_CASE))
}
if (tocStartIdx == -1) {
return
}

// Skipping the blank line after the ## Table of Contents
val tocEndIdx = fileContents.subList(tocStartIdx + 2, fileContents.size).indexOfFirst {
it.startsWith("#")
}.takeIf { it != -1 }
?: error("Wiki doesn't contain headers referenced in Table of Contents.")

val tocSpecificLines = fileContents.subList(tocStartIdx, tocStartIdx + tocEndIdx + 1)

for (line in tocSpecificLines) {
if (line.trimStart().startsWith("- [") && !line.contains("https://")) {
validateTableOfContents(file, line)
}
}
}

private fun validateTableOfContents(file: File, line: String) {
val titleRegex = "\\[(.*?)\\]".toRegex()
val title = titleRegex.find(line)?.groupValues?.get(1)?.replace('-', ' ')
?.replace(Regex("[?&./:’'*!,(){}\\[\\]+]"), "")
?.trim()

val linkRegex = "\\(#(.*?)\\)".toRegex()
val link = linkRegex.find(line)?.groupValues?.get(1)?.removePrefix("#")?.replace('-', ' ')
?.replace(Regex("[?&./:’'*!,(){}\\[\\]+]"), "")
?.trim()

// Checks if the table of content title matches with the header link text.
val matches = title.equals(link, ignoreCase = true)
if (!matches) {
error(
"\nWIKI TABLE OF CONTENTS CHECK FAILED" +
"\nMismatch of Table of Content with headers in the File: ${file.name}. " +
"\nThe Title: '${titleRegex.find(line)?.groupValues?.get(1)}' " +
"doesn't match with its corresponding Link: '${linkRegex.find(line)?.groupValues?.get(1)}'."
)
}
}
16 changes: 16 additions & 0 deletions scripts/src/javatests/org/oppia/android/scripts/wiki/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
"""
Tests corresponding to wiki-related checks.
"""

load("@io_bazel_rules_kotlin//kotlin:jvm.bzl", "kt_jvm_test")

kt_jvm_test(
name = "WikiTableOfContentsCheckTest",
srcs = ["WikiTableOfContentsCheckTest.kt"],
deps = [
"//scripts/src/java/org/oppia/android/scripts/wiki:wiki_table_of_contents_check_lib",
"//testing:assertion_helpers",
"//third_party:com_google_truth_truth",
"//third_party:org_jetbrains_kotlin_kotlin-test-junit",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
package org.oppia.android.scripts.wiki

import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TemporaryFolder
import org.oppia.android.testing.assertThrows
import java.io.ByteArrayOutputStream
import java.io.PrintStream

/** Tests for [WikiTableOfContentsCheck]. */
class WikiTableOfContentsCheckTest {
private val outContent: ByteArrayOutputStream = ByteArrayOutputStream()
private val originalOut: PrintStream = System.out
private val WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR = "WIKI TABLE OF CONTENTS CHECK PASSED"
private val WIKI_TOC_CHECK_FAILED_OUTPUT_INDICATOR = "WIKI TABLE OF CONTENTS CHECK FAILED"

@field:[Rule JvmField] val tempFolder = TemporaryFolder()

@Before
fun setUp() {
System.setOut(PrintStream(outContent))
}

@After
fun tearDown() {
System.setOut(originalOut)
}

@Test
fun testWikiTOCCheck_noWikiDirExists_printsNoContentFound() {
runScript()
assertThat(outContent.toString().trim()).isEqualTo("No contents found in the Wiki directory.")
}

@Test
fun testWikiTOCCheck_noWikiDirectory_printsNoContentFound() {
tempFolder.newFile("wiki")
runScript()
assertThat(outContent.toString().trim()).isEqualTo("No contents found in the Wiki directory.")
}

@Test
fun testWikiTOCCheck_validWikiTOC_checkPass() {
tempFolder.newFolder("wiki")
val file = tempFolder.newFile("wiki/wiki.md")
file.writeText(
"""
## Table of Contents
- [Introduction](#introduction)
- [Usage](#usage)
## Introduction
Content
## Usage
Content
""".trimIndent()
)

runScript()

assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR)
}

@Test
fun testWikiTOCCheck_missingWikiTOC_returnsNoTOCFound() {
tempFolder.newFolder("wiki")
val file = tempFolder.newFile("wiki/wiki.md")
file.writeText(
"""
- [Introduction](#introduction)
- [Usage](#usage)
## Introduction
Content
## Usage
Content
""".trimIndent()
)

runScript()

assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR)
}

@Test
fun testWikiTOCCheck_wikiTOCReference_noHeadersFound_throwsException() {
tempFolder.newFolder("wiki")
val file = tempFolder.newFile("wiki/wiki.md")
file.writeText(
"""
## Table of Contents
- [Introduction](#introductions)
""".trimIndent()
)

val exception = assertThrows<IllegalStateException>() {
runScript()
}

assertThat(exception).hasMessageThat().contains(
"Wiki doesn't contain headers referenced in Table of Contents."
)
}

@Test
fun testWikiTOCCheck_mismatchWikiTOC_checkFail() {
tempFolder.newFolder("wiki")
val file = tempFolder.newFile("wiki/wiki.md")
file.writeText(
"""
## Table of Contents
- [Introduction](#introductions)
- [Usage](#usage)
## Introduction
Content
## Usage
Content
""".trimIndent()
)

val exception = assertThrows<IllegalStateException>() {
runScript()
}

assertThat(exception).hasMessageThat().contains(WIKI_TOC_CHECK_FAILED_OUTPUT_INDICATOR)
}

@Test
fun testWikiTOCCheck_validWikiTOCWithSeparator_checkPass() {
tempFolder.newFolder("wiki")
val file = tempFolder.newFile("wiki/wiki.md")
file.writeText(
"""
## Table of Contents
- [Introduction To Wiki](#introduction-to-wiki)
- [Usage Wiki-Content](#usage-wiki-content)
## Introduction
Content
## Usage
Content
""".trimIndent()
)

runScript()

assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR)
}

@Test
fun testWikiTOCCheck_validWikiTOCWithSpecialCharacter_checkPass() {
tempFolder.newFolder("wiki")
val file = tempFolder.newFile("wiki/wiki.md")
file.writeText(
"""
## Table of Contents
- [Introduction](#introduction?)
- [Usage?](#usage)
## Introduction
Content
## Usage
Content
""".trimIndent()
)

runScript()

assertThat(outContent.toString().trim()).contains(WIKI_TOC_CHECK_PASSED_OUTPUT_INDICATOR)
}

private fun runScript() {
main(tempFolder.root.absolutePath)
}
}
2 changes: 1 addition & 1 deletion wiki/Guidance-on-submitting-a-PR.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Note: If your change involves more than around 500 lines of code, we recommend f
- [Tips for getting your PR submitted](#tips-for-getting-your-pr-submitted)
- [Appendix: Resolving merge conflicts using the terminal](#appendix-resolving-merge-conflicts-using-the-terminal)
- [Appendix: Resolving merge conflicts using Android Studio](#appendix-resolving-merge-conflicts-using-android-studio)
- [Step 4: Tidy up and celebrate!](#step-4-tidy-up-and-celebrate-confetti_ball)
- [Step 4: Tidy up and celebrate! :confetti_ball:](#step-4-tidy-up-and-celebrate-confetti_ball)

## Step 1: Making a local code change

Expand Down
2 changes: 1 addition & 1 deletion wiki/Installing-Oppia-Android.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This wiki page explains how to install Oppia Android on your local machine. If y
- [Prepare developer environment](#prepare-developer-environment)
- [Install oppia-android](#install-oppia-android)
- [Run the app from Android Studio](#run-the-app-from-android-studio)
- [Run the tests](#set-up-and-run-tests)
- [Set up and Run tests](#set-up-and-run-tests)
- [Step-by-Step guidance for setting up and running app modules robolectric test](#step-by-step-guidance-for-setting-up-and-running-app-modules-robolectric-test)
- [For tests that are in non-app modules, such as **domain** or **utility**:](#for-tests-that-are-in-non-app-modules-such-as-domain-or-utility)

Expand Down
2 changes: 1 addition & 1 deletion wiki/Interpreting-CI-Results.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Table of Contents

- [How to find the error message for a Failing CI check](#how-to-find-error-message-for-failing-ci-checks)
- [How to find error message for Failing CI checks](#how-to-find-error-message-for-failing-ci-checks)
- [Developer Video - Understanding CI check failures](#developer-video---understanding-ci-check-failures)

## How to find error message for Failing CI checks
Expand Down
Loading

0 comments on commit 16230b7

Please sign in to comment.