Skip to content

Commit 8a4fa12

Browse files
authored
Fix oppia#19718: Create a pre-push script that runs current pre-push hook in docker container (oppia#19759)
* pre-push-hook helper script * handling docker containers * some minor changes * testing commits * fakeCommits * update script creating wrong symlink * updated script * updated script again * fixed all major issues * removed tempfile * final major fixes * updated some comments * added few more comments * updated comments and fixed minor issues in commands * added codeowner of new file * resolved some issues * moved pre-push docker file to docker folder * updated pre_push_hook.py * solved linting issue * solved linting issue * solved linting issue (3) * solved linting issue (4) * fixed by removing * removed all comments * added comments * updated makefile to install pre push hook on build step * updated make file to install hook using bash * refractor script, updated commments * upadted comments, resolved PYTHON_CMD in docker * updated method to check if oppia is dockerozied in pre_push_hook.py * fixed some issues
1 parent 0173f87 commit 8a4fa12

File tree

3 files changed

+129
-2
lines changed

3 files changed

+129
-2
lines changed

Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@ start-devserver: ## Starts the development server
7171
@echo 'Check dev-server logs using "make logs.dev-server"'
7272
@echo 'Stop the development server using "make stop"'
7373

74-
init: build run-devserver ## Initializes the build and runs dev-server.
74+
init: install-hooks build run-devserver ## Initializes the build and runs dev-server.
75+
76+
install-hooks: ## Install required hooks
77+
bash ./docker/pre_push_hook.sh --install
7578

7679
clean: ## Cleans the docker containers and volumes.
7780
docker compose down --rmi all --volumes

docker/pre_push_hook.sh

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/bin/bash
2+
#
3+
# Copyright 2024 The Oppia Authors. All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the 'License');
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an 'AS-IS' BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# For this script to work properly, you need to have scripts/pre_push_hook.py
18+
# This scripts helps running pre-push hook inside docker container by,
19+
# working as middle layer beteen hook and pre_push_hook.py in docker
20+
# If you can't understand whats going on here, please visit
21+
# https://docs.google.com/document/d/1whHSUEchpmnqxSsRvHU_WYbBzeqVMh7vrjpuA8FMnAM/edit?usp=sharing
22+
#
23+
# To install hook (which runs inside docker container), run this script
24+
# command from oppia root directory with --install argument
25+
#
26+
# Currently it only works for Unix systems, on windows it will create symlink but won't have any effect
27+
28+
DEV_CONTAINER="dev-server"
29+
DOCKER_EXEC_COMMAND="docker compose exec -T $DEV_CONTAINER "
30+
31+
32+
# Location of git hooks directory
33+
HOOKS_DIR=".git/hooks"
34+
35+
# Path for symbolic links to hook files
36+
PRE_PUSH_SYMLINK="$HOOKS_DIR/pre-push"
37+
PYTHON_PRE_PUSH_SYMLINK="$HOOKS_DIR/pre-push-python"
38+
39+
# Path for hook files
40+
PRE_PUSH_FILE="docker/pre_push_hook.sh"
41+
PYTHON_PRE_PUSH_FILE="scripts/pre_push_hook.py"
42+
43+
# Install pre-push hook
44+
install_hook() {
45+
# Create symlinks for pre-push hook files
46+
for file in "$PRE_PUSH_SYMLINK" "$PYTHON_PRE_PUSH_SYMLINK"; do
47+
# Check if pre-push file is already a symlink
48+
if [ -h "$file" ] && [ -e "$file" ]; then
49+
echo "Symlink already exists (for $file)"
50+
51+
else
52+
# If broken symlink, remove it
53+
if [ -h "$file" ] && [ ! -e "$file" ]; then
54+
rm "$file"
55+
echo "Removed broken symlink (for $file)"
56+
fi
57+
58+
# Try creating a symlink
59+
if [ "$(basename $file)" == "pre-push" ]; then
60+
ORIGINAL_FILE="../../$PRE_PUSH_FILE"
61+
else
62+
ORIGINAL_FILE="../../$PYTHON_PRE_PUSH_FILE"
63+
fi
64+
65+
ln -s "$ORIGINAL_FILE" "$file" &&
66+
echo "Created symlink in .git/hooks directory" ||
67+
{
68+
# Fallback to copy on windows
69+
cp "$ORIGINAL_FILE" "$file"
70+
echo "Copied file to .git/hooks directory"
71+
}
72+
73+
# Make the hook file executable
74+
chmod +x "$file"
75+
76+
if [ $? -eq 0 ]; then
77+
echo "pre-push hook file is now executable!"
78+
else
79+
echo >&2 "Failed to make pre-push executable"
80+
exit 1
81+
fi
82+
fi
83+
done
84+
exit 0
85+
}
86+
87+
# Check for --install in args and install pre-push hook if itC's found
88+
for arg in "$@"; do
89+
if [ "$arg" == "--install" ]; then
90+
install_hook
91+
fi
92+
done
93+
94+
# Check if dev-server is running and is healthy
95+
$(docker ps -a --format '{{json .}}' | grep $DEV_CONTAINER | jq .Status | grep -q healthy)
96+
is_container_running=$?
97+
98+
if [ "$is_container_running" != "0" ]; then
99+
# Start containers and run pre-push hook
100+
make start-devserver # We don't need to use run-offline as internet would be available when pushing commit
101+
fi
102+
103+
# Run hook in container
104+
CMD="$DOCKER_EXEC_COMMAND python3 ./$PYTHON_PRE_PUSH_SYMLINK $@"
105+
echo "Running $CMD"
106+
107+
$CMD
108+
109+
# Save exit code from the docker command, so we can later use it to exit this pre-push hook at end.
110+
exitcode=$?
111+
echo "Python script exited with code $exitcode"
112+
113+
# Shut down containers if they were not running before pre-push hook execution.
114+
if [ "$is_container_running" != "0" ]; then
115+
make stop
116+
fi
117+
118+
# Exit with exit code from container
119+
exit $exitcode

scripts/pre_push_hook.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
sys.path.append(os.getcwd())
4747
from scripts import common # isort:skip # pylint: disable=wrong-import-position
4848
from scripts import install_python_prod_dependencies # isort:skip # pylint: disable=wrong-import-position
49+
from core import feconf #isort:skip # pylint: disable=wrong-import-position
4950

5051
GitRef = collections.namedtuple(
5152
'GitRef', ['local_ref', 'local_sha1', 'remote_ref', 'remote_sha1'])
@@ -60,7 +61,11 @@
6061
FILE_DIR: Final = os.path.abspath(os.path.dirname(__file__))
6162
OPPIA_DIR: Final = os.path.join(FILE_DIR, os.pardir, os.pardir)
6263
LINTER_FILE_FLAG: Final = '--files'
63-
PYTHON_CMD: Final = 'python'
64+
65+
# Path to currently running python interpreter,
66+
# it is required to resolve python version conflict in docker.
67+
PYTHON_CMD: Final = sys.executable if feconf.OPPIA_IS_DOCKERIZED else 'python'
68+
6469
OPPIA_PARENT_DIR: Final = os.path.join(
6570
FILE_DIR, os.pardir, os.pardir, os.pardir
6671
)

0 commit comments

Comments
 (0)