Skip to content

Commit 01295a4

Browse files
authored
V2.2.6 fixs (#78)
* fixes * ADD blog 1 * FIX markdown to jsx translation * FIX optomize dockerfiles and fix animations
1 parent 403e322 commit 01295a4

22 files changed

+482
-182
lines changed

api/Dockerfile

+15-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,24 @@ WORKDIR /opt/app
66

77
COPY requirements.txt requirements.txt
88

9-
RUN apk add --update --no-cache mariadb-client git curl tzdata gcc musl-dev libmagic \
9+
RUN apk add --update --no-cache mariadb-client git tzdata gcc g++ musl-dev libmagic \
1010
&& pip3 install --no-cache-dir -r ./requirements.txt \
1111
&& adduser -D anubis \
1212
&& chown anubis:anubis -R /opt/app \
13-
&& ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime
13+
&& ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime \
14+
&& apk del gcc g++ \
15+
&& env USER=root find /opt/app -depth \
16+
\( \
17+
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
18+
-o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name '*.a' \) \) \
19+
\) -exec rm -rf '{}' + \
20+
\
21+
&& env USER=root find /usr/local -depth \
22+
\( \
23+
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
24+
-o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name '*.a' \) \) \
25+
\) -exec rm -rf '{}' +
26+
1427

1528
USER anubis
1629

api/anubis/app.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ def init_services(app):
99
:param app: Flask app
1010
:return:
1111
"""
12-
from anubis.models import db
13-
from anubis.utils.cache import cache
12+
from anubis.config import config
13+
from anubis.models import db, Config
14+
from anubis.utils.cache import cache, cache_health
1415
from anubis.utils.migrate import migrate
1516
from anubis.utils.elastic import add_global_error_handler
16-
from anubis.config import config
1717

1818
# Init services
1919
db.init_app(app)
@@ -22,7 +22,9 @@ def init_services(app):
2222

2323
@app.route("/")
2424
def index():
25-
return "Hello there..."
25+
Config.query.all()
26+
cache_health()
27+
return "Healthy"
2628

2729
# Add ELK stuff
2830
if not config.DISABLE_ELK:

api/anubis/models/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,7 @@ def data(self):
448448
"state": self.state,
449449
"created": str(self.created),
450450
"last_updated": str(self.last_updated),
451+
"error": self.errors is not None,
451452
}
452453

453454
@property

api/anubis/rpc/pipeline.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from anubis.models import Config, Submission
99
from anubis.utils.logger import logger
10-
10+
from anubis.utils.data import is_debug
1111

1212
def create_pipeline_job_obj(client, submission):
1313
"""

api/anubis/utils/cache.py

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
from flask_caching import Cache
22

33
cache = Cache(config={"CACHE_TYPE": "redis"})
4+
5+
6+
@cache.cached(timeout=1)
7+
def cache_health():
8+
pass

docs/design.md

+127-128
Large diffs are not rendered by default.

docs/img/theia-fullscreen.png

366 KB
Loading

docs/posts/1.md

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Anubis Autograder
2+
3+
![](../img/anubis-icon-1.png)
4+
5+
## Elevator Pitch
6+
7+
At its core, Anubis is a tool to give students live feedback from their homework
8+
assignments
9+
while they are working on them. Using [Github Classrooms](https://classroom.github.com/),
10+
each student gets their
11+
own repo from a template
12+
for each homework assignment. The way students then submit their work
13+
is simply by pushing their work to their repo before the deadline. Students can
14+
then push, and therefore submit as many times as
15+
they would like before the deadline.
16+
17+
## Assignment structure
18+
19+
When a student pushes to their assignment repo, a job is launched on the Anubis
20+
cluster. That job will build
21+
their repo, run tests on the results, and store the results in a database.
22+
23+
Students can then navigate to the Anubis website, where
24+
they will sign in through NYU SSO.
25+
From there,
26+
they will be able to see all the current and past assignments,
27+
and all of their submissions. They are able
28+
to view the results of the build and tests for each submission.
29+
There they can request a regrade,
30+
there by launching a new submission pipeline. While the submission
31+
still being processed, the website will poll
32+
the backend for updates. In this, the website will be constantly
33+
updating while the submission is being
34+
processed, giving a live and interactive feel to the site. Once
35+
a submission is processed Anubis will show
36+
the students logs from their tests, and builds along with which
37+
tests passed and which failed.
38+
39+
![alt autogade-results](../img/autograde-results.png)
40+
41+
## Anubis Cloud IDEs
42+
43+
New in version v2.2.0, there is now the Anubis Cloud IDE. Using some
44+
kubernetes magic, we are able to
45+
host [theia](https://theia-ide.org/) servers for individual students.
46+
These are essentially
47+
VSCode instances
48+
that students can access in the browser. What makes these so powerful
49+
is that students can access a terminal
50+
and type commands right into a bash shell which will be run in the
51+
remote container. With this setup students
52+
have access to a fully insulated and prebuilt linux
53+
environment at a click of a button. These environments are easily customizable
54+
for the needs of the class or even individual assignments. Because these
55+
IDE servers are light weight docker containers we can support
56+
many more students than if we used VMs. There are ~130 students in the Intro
57+
to OS course in spring of 2021, and we could support all of them
58+
using IDEs at the same time while still processing all the submissions that
59+
come through.
60+
61+
As we are giving students access to a terminal in the cloud, we must also lock
62+
down their environment. All student IDEs are limited in the RAM, CPU, storage,
63+
and networking. From the IDEs, students are only able to connect to Github to
64+
submit their work.
65+
66+
![alt anubis-ide](../img/theia-fullscreen.png)
67+
68+
69+
70+
> Does any of this sound appealing to you? Reach out to us to see if Anubis is
71+
something that can benefit your class!

kube/templates/api.yml

+5-6
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,11 @@ spec:
8484
value: {{ .Values.theia.proxy.domain | quote }}
8585
{{- if .Values.api.healthCheck }}
8686
livenessProbe:
87-
exec:
88-
command:
89-
- curl
90-
- http://localhost:5000/
91-
initialDelaySeconds: 10
92-
periodSeconds: 5
87+
httpGet:
88+
path: /
89+
port: 5000
90+
initialDelaySeconds: 15
91+
periodSeconds: 3
9392
{{- end }}
9493

9594
# Mail container

theia/sidecar/supervisord.conf

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ logfile=/supervisord.log
44
[program:autosave-loop]
55
directory=/
66
command=/autosave-loop.sh
7+
environment=HOME="/home/theia"
78
autorestart=true
89
user=theia
9-
stdout_logfile=/dev/fd/1
10-
stdout_logfile_maxbytes=0
10+
redirect_stderr=true
11+
stdout_logfile=/home/theia/autosave.log
1112

1213
[program:autosave-server]
1314
directory=/
1415
command=gunicorn -b 0.0.0.0:5001 -w 1 app:app
1516
autorestart=true
1617
environment=HOME="/home/theia"
1718
user=theia
18-
stdout_logfile=/dev/fd/1
19-
stdout_logfile_maxbytes=0
19+
redirect_stderr=true
20+
stdout_logfile=/home/theia/server.log

web/Dockerfile

+8-8
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
FROM node:alpine
2-
32
WORKDIR /opt/app
43
COPY package.json .
54
COPY yarn.lock .
6-
7-
# install dependencies
8-
# add program for serving static
9-
# build prod
10-
# delete fluff
11-
RUN apk add --update --no-cache curl && yarn \
12-
&& yarn global add serve
5+
RUN yarn
136
COPY . .
147
RUN yarn run build \
158
&& rm -rf node_modules src public package.json yarn.lock
169

10+
11+
FROM node:alpine
12+
WORKDIR /opt/app
13+
RUN apk add --update --no-cache curl && yarn global add serve
14+
COPY --from=0 /opt/app/build /opt/app/build
15+
16+
1717
CMD serve -s build -l 3000

web/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"axios": "^0.21.1",
1818
"clsx": "^1.1.0",
1919
"date-fns": "^2.0.0",
20+
"markdown-to-jsx": "^7.1.2",
2021
"notistack": "^1.0.3",
2122
"react": "^17.0.1",
2223
"react-ace": "^9.2.0",

web/public/anubis-icon-1.png

14.1 KB
Loading

web/public/autograde-results-1.png

362 KB
Loading

web/public/theia-fullscreen.png

366 KB
Loading

web/src/Components/Public/IDE/IDEDialog.jsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,7 @@ export default function IDEDialog({selectedTheia, setSelectedTheia}) {
140140
setSession(data.session);
141141
}
142142
if (data?.session?.autosave !== undefined) {
143-
console.log('autosave', data.session.autosave);
144-
setAutosaveEnabled(data.autosaveEnabled);
143+
setAutosaveEnabled(data.session.autosave);
145144
}
146145
}).catch(standardErrorHandler(enqueueSnackbar));
147146
}, [selectedTheia]);

web/src/Components/Public/Submission/SubmissionSummary.jsx

+29-9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import TableCell from '@material-ui/core/TableCell';
2121
import Divider from '@material-ui/core/Divider';
2222
import {useSnackbar} from 'notistack';
2323
import clsx from 'clsx';
24+
import Fab from '@material-ui/core/Fab';
2425

2526
const useStyles = makeStyles((theme) => ({
2627
root: {
@@ -40,7 +41,7 @@ const useStyles = makeStyles((theme) => ({
4041
},
4142
}));
4243

43-
export default function SubmissionSummary({submission, regrade, stop = false}) {
44+
export default function SubmissionSummary({submission, regrade, stop}) {
4445
const classes = useStyles();
4546
const {enqueueSnackbar} = useSnackbar();
4647

@@ -64,6 +65,28 @@ export default function SubmissionSummary({submission, regrade, stop = false}) {
6465
const testsPassed = submission.tests.filter((test) => test.result.passed).length;
6566
const totalTests = submission.tests.length;
6667

68+
const ReloadIcon = () => (
69+
<Tooltip title={'regrade'}>
70+
<Fab
71+
onClick={() => regrade(submission.commitHash, enqueueSnackbar)}
72+
size={'small'}
73+
color={'primary'}
74+
>
75+
<RefreshIcon/>
76+
</Fab>
77+
</Tooltip>
78+
);
79+
80+
const LoadingIcon = () => (
81+
<Tooltip title={submission.state}>
82+
<IconButton
83+
onClick={() => regrade(submission.commitHash, enqueueSnackbar)}
84+
>
85+
<CircularProgress size="1em"/>
86+
</IconButton>
87+
</Tooltip>
88+
);
89+
6790
return (
6891
<Card className={classes.root}>
6992
<CardActionArea>
@@ -134,14 +157,11 @@ export default function SubmissionSummary({submission, regrade, stop = false}) {
134157
{/* Submission state */}
135158
<ListItem>
136159
<ListItemIcon>
137-
<Tooltip title={!submission.processed ? submission.state : 'regrade'}>
138-
<IconButton component="div" onClick={() =>
139-
regrade(submission.commitHash, enqueueSnackbar)}>
140-
{(submission.processed && !stop) ?
141-
<RefreshIcon color={'primary'}/> :
142-
<CircularProgress size="1em"/>}
143-
</IconButton>
144-
</Tooltip>
160+
{stop ? <ReloadIcon/> : (
161+
submission.processed ?
162+
<ReloadIcon/> :
163+
<LoadingIcon/>
164+
)}
145165
</ListItemIcon>
146166
<ListItemText primary={submission.state}/>
147167
</ListItem>

web/src/Components/Public/Submission/SubmissionTests.jsx

+16-8
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,25 @@ export default function SubmissionTests({tests, stop}) {
5050
<div className={classes.wrapper}>
5151
<Fab
5252
aria-label="save"
53-
color={test.result.passed === false ? 'secondary' : 'primary'}
53+
color={stop ? 'secondary' : (test.result.passed === false ? 'secondary' : 'primary')}
5454
>
55-
{test.result.passed === null ? (
56-
<AssessmentIcon/>
57-
) : (test.result.passed === true && !stop) ? (
58-
<CheckCircleIcon/>
59-
) : (test.result.passed === false || stop) ? (
55+
{stop ? (
6056
<CancelIcon/>
61-
) : null}
57+
) : (
58+
<React.Fragment>
59+
{test.result.passed === null ? (
60+
<AssessmentIcon/>
61+
) : (test.result.passed === true) ? (
62+
<CheckCircleIcon/>
63+
) : (test.result.passed === false) ? (
64+
<CancelIcon/>
65+
) : null}
66+
</React.Fragment>
67+
)}
6268
</Fab>
63-
{test.result.passed === null && <CircularProgress size={68} className={classes.fabProgress}/>}
69+
{stop ? null : (
70+
test.result.passed === null && <CircularProgress size={68} className={classes.fabProgress}/>
71+
)}
6472
</div>
6573
<Typography className={classes.heading}>{test.test.name}</Typography>
6674
</AccordionSummary>

web/src/Navigation/navconfig.jsx

+18-7
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import GroupIcon from '@material-ui/icons/Group';
1111
import SettingsIcon from '@material-ui/icons/Settings';
1212
import PieChartIcon from '@material-ui/icons/PieChart';
1313
import AttachFileIcon from '@material-ui/icons/AttachFile';
14+
import BookIcon from '@material-ui/icons/Book';
1415

1516
import About from '../Pages/Public/About';
1617
import Courses from '../Pages/Public/Courses';
@@ -19,6 +20,7 @@ import Profile from '../Pages/Public/Profile';
1920
import Repos from '../Pages/Public/Repos';
2021
import Submissions from '../Pages/Public/Submissions';
2122
import Submission from '../Pages/Public/Submission';
23+
import Blog from '../Pages/Public/Blog';
2224

2325
import AdminUsers from '../Pages/Admin/Users';
2426
import AdminUser from '../Pages/Admin/User';
@@ -31,13 +33,22 @@ import AdminTheia from '../Pages/Admin/Theia';
3133
import AdminStatic from '../Pages/Admin/Static';
3234
import AdminConfig from '../Pages/Admin/Config';
3335

34-
export const footer_nav = [{
35-
id: 'About',
36-
icon: <PublicIcon/>,
37-
exact: true,
38-
path: '/about',
39-
Page: About,
40-
}];
36+
export const footer_nav = [
37+
{
38+
id: 'About',
39+
icon: <PublicIcon/>,
40+
exact: true,
41+
path: '/about',
42+
Page: About,
43+
},
44+
{
45+
id: 'Blog',
46+
icon: <BookIcon/>,
47+
exact: true,
48+
path: '/blog',
49+
Page: Blog,
50+
},
51+
];
4152

4253
export const public_nav = [
4354
{

0 commit comments

Comments
 (0)