Skip to content

Commit 4be7404

Browse files
committed
feat: lab0
1 parent 3a9c7ca commit 4be7404

9 files changed

+238
-0
lines changed

.github/pull_request_template.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## Description
2+
3+
<!-- You can check sample PR here: (remember to delete this link when you create your PR) -->
4+
<https://github.com/SQLab/112-spring-software-testing/pull/2>
5+
6+
<!-- Please briefly describe your change here -->
7+
8+
---
9+
10+
<!-- Please make sure you're satisfied and fill in the following checkboxes -->
11+
<!-- A good PR should include the following parts: -->
12+
13+
- [ ] A clear title (name your PR "[LAB{lab_number}] {your_student_id}")
14+
- [ ] A meaningful message for PR, as well as its commits
15+
- [ ] From your specific branch (***not main or other's branch***) merging to your branch
16+
- [ ] Excluding any irrelevant files, such as binaries, text files, or dot files
17+
- [ ] Passing all CI (You should check it first to pass one of the validations in CI. However, you need to make sure your PR passes all CI after you submit it.)

.github/workflows/PR.yml

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: PR automation
2+
on:
3+
pull_request_target:
4+
types: [opened, reopened, edited, ready_for_review]
5+
6+
jobs:
7+
labeler:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Label PR
11+
uses: actions/github-script@v5
12+
with:
13+
github-token: ${{ secrets.PAT }}
14+
script: |
15+
const { owner, repo, number: issue_number } = context.issue;
16+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: issue_number });
17+
const title = pr.data.title;
18+
19+
const titleRegex = /^\[LAB(\d+)\] [a-zA-Z]?\d+$/;
20+
const match = title.match(titleRegex);
21+
22+
let labNumberStr = undefined;
23+
if (match) {
24+
labNumberStr = match[1];
25+
} else {
26+
core.setFailed('PR title does not match the required format. Please use the format: [LAB#] <studentId>.');
27+
}
28+
29+
const labelToAdd = `lab${labNumberStr}`;
30+
if (labNumberStr) {
31+
await github.rest.issues.addLabels({ owner, repo, issue_number, labels: [labelToAdd] });
32+
}
33+
34+
if (pr.data.base.ref === 'main') {
35+
core.setFailed('The target branch cannot be main.');
36+
}
37+
38+
if (labNumberStr < 3 && pr.data.head.ref !== pr.data.base.ref) {
39+
core.setFailed('The source branch and target branch must be the same.');
40+
}
41+
if (labNumberStr >= 3 && pr.data.head.ref !== labelToAdd) {
42+
core.setFailed(`The source branch must be '${labelToAdd}'`);
43+
}
44+
checklist-check:
45+
runs-on: ubuntu-latest
46+
steps:
47+
- name: Check PR description
48+
uses: actions/github-script@v5
49+
with:
50+
github-token: ${{ secrets.GITHUB_TOKEN }}
51+
script: |
52+
const { owner, repo, number: issue_number } = context.issue;
53+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: issue_number });
54+
const body = pr.data.body;
55+
56+
const checkboxes = body.match(/^ ?(-|\*) \[[x ]\]/gmi);
57+
if (!checkboxes || checkboxes.length !== 5) {
58+
core.setFailed('The PR description must contain exactly 5 checkboxes.');
59+
}
60+
61+
const unchecked = body.match(/^ ?(-|\*) \[ \]/gm);
62+
if (unchecked && unchecked.length > 0) {
63+
core.setFailed(`There are ${unchecked.length} unchecked item(s) in the PR description.`);
64+
}

.github/workflows/lab-autograding.yml

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Autograding
2+
3+
on:
4+
pull_request_target:
5+
types: [labeled, synchronize, opened, reopened, ready_for_review]
6+
7+
jobs:
8+
build:
9+
runs-on: ${{ matrix.os }}
10+
strategy:
11+
matrix:
12+
os: [ubuntu-22.04]
13+
fail-fast: false
14+
steps:
15+
- uses: actions/checkout@v4
16+
with:
17+
ref: "${{ github.event.pull_request.merge_commit_sha }}"
18+
fetch-depth: 1
19+
- uses: actions/setup-node@v4
20+
with:
21+
node-version: latest
22+
- name: Extract lab number and Check no changes other than specific files
23+
uses: actions/github-script@v5
24+
id: lab
25+
with:
26+
result-encoding: string
27+
github-token: ${{ secrets.GITHUB_TOKEN }}
28+
script: |
29+
const { owner, repo, number: issue_number } = context.issue;
30+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: issue_number });
31+
const labels = pr.data.labels;
32+
const lab = labels.find((label) => label.name.startsWith('lab'));
33+
if (!lab) {
34+
core.setFailed('No lab label found on the PR.');
35+
return { number: 0 };
36+
}
37+
const labNumberMatch = lab.name.match(/lab(\d+)/);
38+
if (!labNumberMatch) {
39+
core.setFailed('Invalid lab label found on the PR.');
40+
return { number: 0 };
41+
}
42+
const labNumber = labNumberMatch[1];
43+
console.log(`Lab number: ${labNumber}`)
44+
45+
const files = await github.rest.pulls.listFiles({ owner, repo, pull_number: issue_number });
46+
const changedFiles = files.data.map((file) => file.filename);
47+
const allowedFileRegex = /^lab\d+\/main_test.js$/;
48+
const specialChangedFiles = ["lab0.js"];
49+
if (!changedFiles.every((file) => (allowedFileRegex.test(file) || specialChangedFiles.includes(file)))) {
50+
core.setFailed('The PR contains changes to files other than the allowed files.');
51+
}
52+
return labNumber;
53+
- name: Grading
54+
run: |
55+
cd lab${{ steps.lab.outputs.result }}
56+
./validate.sh

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules/

lab0/README.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Lab1
2+
3+
## Introduction
4+
5+
In this lab, you will write a program that outputs "Hello world!" in `lab0.js`. You can learn how to submit your lab for this class.
6+
7+
## Requirement
8+
9+
1. Write test cases in `lab0.js` and print "Hello world!". (100%)
10+
11+
You can run `validate.sh` in your local to test if you satisfy the requirements.
12+
13+
Please note that you must not alter files other than `lab0.js`. You will get 0 points if you modify other files to achieve requirements.
14+
15+
## Submission
16+
17+
You need to open a pull request to your branch (e.g. 312XXXXXX, your student number) and contain the code that satisfies the abovementioned requirements.
18+
19+
Moreover, please submit the URL of your PR to E3. Your submission will only be accepted when you present at both places.

lab0/lab0.js

Whitespace-only changes.

lab0/validate.sh

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
3+
node=$(which node)
4+
test_path="${BASH_SOURCE[0]}"
5+
solution_path="$(realpath .)"
6+
tmp_dir=$(mktemp -d -t lab1-XXXXXXXXXX)
7+
8+
cd $tmp_dir
9+
10+
rm -rf *
11+
cp $solution_path/*.js .
12+
result=$($"node" lab0.js) ; ret=$?
13+
if [ $ret -ne 0 ] ; then
14+
echo "[!] Failed"
15+
exit 1
16+
else
17+
if [[ $result != "Hello world!" ]]; then
18+
echo "[!] Failed"
19+
exit 1
20+
else
21+
echo "[V] Pass"
22+
fi
23+
fi
24+
25+
rm -rf $tmp_dir
26+
27+
exit 0
28+
29+
# vim: set fenc=utf8 ff=unix et sw=2 ts=2 sts=2:

scripts/merge-all.sh

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash
2+
3+
if [ $# -ne 1 ]; then
4+
echo "$0 <commit-message>"
5+
exit 1
6+
fi
7+
8+
git fetch origin
9+
10+
for branch in $(git branch -r | grep -v HEAD); do
11+
# Remove the "origin/" prefix
12+
branch=${branch#origin/}
13+
14+
if [[ "$branch" != "main" ]]; then
15+
git checkout "$branch"
16+
if [[ $? -ne 0 ]]; then
17+
echo "Checkout failed for branch $branch"
18+
exit 1
19+
fi
20+
git merge --squash -s recursive -X theirs main
21+
if [[ $? -ne 0 ]]; then
22+
echo "Merge failed for branch $branch"
23+
exit 1
24+
fi
25+
git commit -m "$1"
26+
fi
27+
done
28+
29+
git checkout main

scripts/rebase-all.sh

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
3+
git fetch origin
4+
5+
for branch in $(git branch -r | grep -v HEAD); do
6+
# Remove the "origin/" prefix
7+
branch=${branch#origin/}
8+
9+
if [[ "$branch" != "main" ]]; then
10+
git checkout "$branch"
11+
if [[ $? -ne 0 ]]; then
12+
echo "Checkout failed for branch $branch"
13+
exit 1
14+
fi
15+
git rebase main
16+
if [[ $? -ne 0 ]]; then
17+
echo "Rebase failed for branch $branch"
18+
exit 1
19+
fi
20+
fi
21+
done
22+
23+
git checkout main

0 commit comments

Comments
 (0)