Skip to content

Commit 46bd732

Browse files
authored
Various updates to CI scripts (#118)
- Break out dependency download logic into separate scripts - Switch to using latest tlapm release in anticipation of rolling releases - Switch to using M1 macOS github CI runners Signed-off-by: Andrew Helwer <[email protected]>
1 parent 789a653 commit 46bd732

File tree

8 files changed

+654
-124
lines changed

8 files changed

+654
-124
lines changed

.github/scripts/linux-setup.sh

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# This script downloads all necessary dependencies to run the CI on Linux.
2+
# It can also be run locally, as long as you have the following dependencies:
3+
# - python 3.1x
4+
# - java
5+
# - C & C++ compiler (aliased to cc and cpp commands respectively)
6+
# - wget
7+
# - tar
8+
#
9+
# The script takes the following positional command line parameters:
10+
# 1. Path to this script directory from the current working directory
11+
# 2. Path to the desired dependencies directory
12+
# 3. Boolean true/false; whether to initialize a python virtual env
13+
14+
main() {
15+
# Validate command line parameters
16+
if [ $# -ne 3 ]; then
17+
echo "Usage: $0 <script dir path> <desired dependency dir path> <bool: use python venv>"
18+
exit 1
19+
fi
20+
SCRIPT_DIR="$1"
21+
DEPS_DIR="$2"
22+
USE_VENV=$3
23+
# Print out tool version information
24+
java --version
25+
python --version
26+
pip --version
27+
cc --version
28+
cpp --version
29+
# Install python packages
30+
if $USE_VENV; then
31+
python -m venv .
32+
source bin/activate
33+
pip install -r "$SCRIPT_DIR/requirements.txt"
34+
deactivate
35+
else
36+
pip install -r "$SCRIPT_DIR/requirements.txt"
37+
fi
38+
# Put all dependencies in their own directory to ensure they aren't included implicitly
39+
mkdir -p "$DEPS_DIR"
40+
# Get tree-sitter-tlaplus
41+
wget -nv https://github.com/tlaplus-community/tree-sitter-tlaplus/archive/main.tar.gz -O /tmp/tree-sitter-tlaplus.tar.gz
42+
tar -xzf /tmp/tree-sitter-tlaplus.tar.gz --directory "$DEPS_DIR"
43+
mv "$DEPS_DIR/tree-sitter-tlaplus-main" "$DEPS_DIR/tree-sitter-tlaplus"
44+
# Get TLA⁺ tools
45+
mkdir -p "$DEPS_DIR/tools"
46+
wget -nv http://nightly.tlapl.us/dist/tla2tools.jar -P "$DEPS_DIR/tools"
47+
# Get TLA⁺ community modules
48+
mkdir -p "$DEPS_DIR/community"
49+
wget -nv https://github.com/tlaplus/CommunityModules/releases/latest/download/CommunityModules-deps.jar \
50+
-O "$DEPS_DIR/community/modules.jar"
51+
# Get TLAPS modules
52+
wget -nv https://github.com/tlaplus/tlapm/archive/main.tar.gz -O /tmp/tlapm.tar.gz
53+
tar -xzf /tmp/tlapm.tar.gz --directory "$DEPS_DIR"
54+
mv "$DEPS_DIR/tlapm-main" "$DEPS_DIR/tlapm"
55+
# Install TLAPS
56+
kernel=$(uname -s)
57+
if [ "$kernel" == "Linux" ]; then
58+
TLAPM_BIN_TYPE=x86_64-linux-gnu
59+
elif [ "$kernel" == "Darwin" ]; then
60+
TLAPM_BIN_TYPE=i386-darwin
61+
else
62+
echo "Unknown OS: $kernel"
63+
exit 1
64+
fi
65+
TLAPM_BIN="tlaps-1.5.0-$TLAPM_BIN_TYPE-inst.bin"
66+
wget -nv "https://github.com/tlaplus/tlapm/releases/latest/download/$TLAPM_BIN" -O /tmp/tlapm-installer.bin
67+
chmod +x /tmp/tlapm-installer.bin
68+
# Workaround for https://github.com/tlaplus/tlapm/issues/88
69+
set +e
70+
for ((attempt = 1; attempt <= 5; attempt++)); do
71+
rm -rf "$DEPS_DIR/tlapm-install"
72+
/tmp/tlapm-installer.bin -d "$DEPS_DIR/tlapm-install"
73+
if [ $? -eq 0 ]; then
74+
exit 0
75+
fi
76+
done
77+
exit 1
78+
}
79+
80+
main "$@"
81+

.github/scripts/parse_modules.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,41 @@
1616
parser.add_argument('--community_modules_jar_path', help='Path to the CommunityModules-deps.jar file', required=True)
1717
parser.add_argument('--manifest_path', help='Path to the tlaplus/examples manifest.json file', required=True)
1818
parser.add_argument('--skip', nargs='+', help='Space-separated list of .tla modules to skip parsing', required=False, default=[])
19+
parser.add_argument('--only', nargs='+', help='If provided, only parse models in this space-separated list', required=False, default=[])
20+
parser.add_argument('--verbose', help='Set logging output level to debug', action='store_true')
1921
args = parser.parse_args()
2022

21-
logging.basicConfig(level=logging.INFO)
23+
logging.basicConfig(level = logging.DEBUG if args.verbose else logging.INFO)
2224

2325
tools_jar_path = normpath(args.tools_jar_path)
2426
tlaps_modules = normpath(args.tlapm_lib_path)
2527
community_modules = normpath(args.community_modules_jar_path)
2628
manifest_path = normpath(args.manifest_path)
2729
examples_root = dirname(manifest_path)
2830
skip_modules = [normpath(path) for path in args.skip]
31+
only_modules = [normpath(path) for path in args.only]
2932

3033
def parse_module(path):
3134
"""
3235
Parse the given module using SANY.
3336
"""
3437
logging.info(path)
3538
# Jar paths must go first
36-
search_paths = pathsep.join([tools_jar_path, community_modules, dirname(path), tlaps_modules])
39+
search_paths = pathsep.join([tools_jar_path, dirname(path), community_modules, tlaps_modules])
3740
sany = subprocess.run([
3841
'java',
3942
'-cp', search_paths,
4043
'tla2sany.SANY',
4144
'-error-codes',
4245
path
4346
], capture_output=True)
44-
if sany.returncode != 0:
45-
logging.error(sany.stdout.decode('utf-8'))
47+
output = ' '.join(sany.args) + '\n' + sany.stdout.decode('utf-8')
48+
if 0 == sany.returncode:
49+
logging.debug(output)
50+
return True
51+
else:
52+
logging.error(output)
4653
return False
47-
return True
4854

4955
manifest = tla_utils.load_json(manifest_path)
5056

@@ -54,13 +60,14 @@ def parse_module(path):
5460
for spec in manifest['specifications']
5561
for module in spec['modules']
5662
if normpath(module['path']) not in skip_modules
63+
and (only_modules == [] or normpath(module['path']) in only_modules)
5764
]
5865

5966
for path in skip_modules:
6067
logging.info(f'Skipping {path}')
6168

6269
# Parse specs in parallel
63-
thread_count = cpu_count()
70+
thread_count = cpu_count() if not args.verbose else 1
6471
logging.info(f'Parsing using {thread_count} threads')
6572
with ThreadPoolExecutor(thread_count) as executor:
6673
results = executor.map(parse_module, modules)

.github/scripts/windows-setup.sh

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# This script downloads all necessary dependencies to run the CI on Windows.
2+
# It can also be run locally, as long as you have the following dependencies:
3+
# - python 3.1x
4+
# - java
5+
# - curl
6+
# - 7-zip
7+
#
8+
# The script takes the following positional command line parameters:
9+
# 1. Path to this script directory from the current working directory
10+
# 2. Path to the desired dependencies directory
11+
# 3. Boolean true/false; whether to initialize a python virtual env
12+
13+
main() {
14+
# Validate command line parameters
15+
if [ $# -ne 3 ]; then
16+
echo "Usage: $0 <script dir path> <desired dependency dir path> <bool: use python venv>"
17+
exit 1
18+
fi
19+
SCRIPT_DIR="$1"
20+
DEPS_DIR="$2"
21+
USE_VENV=$3
22+
# Print out tool version information
23+
java --version
24+
python --version
25+
pip --version
26+
# Install python packages
27+
if $USE_VENV; then
28+
python -m venv .
29+
pwsh Scripts/Activate.ps1
30+
pip install -r "$SCRIPT_DIR/requirements.txt"
31+
deactivate
32+
else
33+
pip install -r "$SCRIPT_DIR/requirements.txt"
34+
fi
35+
# Put all dependencies in their own directory to ensure they aren't included implicitly
36+
mkdir -p "$DEPS_DIR"
37+
# Get tree-sitter-tlaplus
38+
curl -L https://github.com/tlaplus-community/tree-sitter-tlaplus/archive/main.zip --output tree-sitter-tlaplus.zip
39+
7z x tree-sitter-tlaplus.zip
40+
mv tree-sitter-tlaplus-main "$DEPS_DIR/tree-sitter-tlaplus"
41+
rm tree-sitter-tlaplus.zip
42+
# Get TLA⁺ tools
43+
mkdir -p "$DEPS_DIR/tools"
44+
curl http://nightly.tlapl.us/dist/tla2tools.jar --output "$DEPS_DIR/tools/tla2tools.jar"
45+
# Get TLA⁺ community modules
46+
mkdir -p "$DEPS_DIR/community"
47+
curl -L https://github.com/tlaplus/CommunityModules/releases/latest/download/CommunityModules-deps.jar --output "$DEPS_DIR/community/modules.jar"
48+
# Get TLAPS modules
49+
curl -L https://github.com/tlaplus/tlapm/archive/main.zip --output tlapm.zip
50+
7z x tlapm.zip
51+
mv tlapm-main "$DEPS_DIR/tlapm"
52+
rm tlapm.zip
53+
}
54+
55+
main "$@"
56+

.github/workflows/CI.yml

+26-101
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ jobs:
1818
include:
1919
- { os: windows-latest }
2020
- { os: ubuntu-latest }
21-
- { os: macos-latest }
21+
- { os: macos-14 }
2222
fail-fast: false
2323
env:
2424
SCRIPT_DIR: .github/scripts
25-
TLAPS_VERSION: 202210041448
25+
DEPS_DIR: deps
2626
defaults:
2727
run:
2828
shell: bash
@@ -32,93 +32,18 @@ jobs:
3232
- name: Install python
3333
uses: actions/setup-python@v5
3434
with:
35-
python-version: '3.11'
35+
python-version: '3.12'
3636
- name: Install Java
3737
uses: actions/setup-java@v4
3838
with:
3939
distribution: adopt
4040
java-version: 17
41-
- name: Download TLA⁺ dependencies
41+
- name: Download TLA⁺ dependencies (Windows)
4242
if: matrix.os == 'windows-latest'
43-
run: |
44-
# Print out tool version information
45-
java --version
46-
python --version
47-
pip --version
48-
# Install python packages
49-
pip install -r $SCRIPT_DIR/requirements.txt
50-
# Put all dependencies in their own directory to ensure they aren't included implicitly
51-
mkdir deps
52-
# Get tree-sitter-tlaplus
53-
curl -LO https://github.com/tlaplus-community/tree-sitter-tlaplus/archive/main.zip
54-
7z x main.zip
55-
rm main.zip
56-
mv tree-sitter-tlaplus-main deps/tree-sitter-tlaplus
57-
# Get TLA⁺ tools
58-
mkdir deps/tools
59-
curl -LO http://nightly.tlapl.us/dist/tla2tools.jar
60-
mv tla2tools.jar deps/tools/tla2tools.jar
61-
# Get TLA⁺ community modules
62-
mkdir deps/community
63-
curl -LO https://github.com/tlaplus/CommunityModules/releases/latest/download/CommunityModules-deps.jar
64-
mv CommunityModules-deps.jar deps/community/modules.jar
65-
# Get TLAPS modules
66-
curl -LO https://github.com/tlaplus/tlapm/archive/refs/tags/$TLAPS_VERSION.zip
67-
7z x $TLAPS_VERSION.zip
68-
rm $TLAPS_VERSION.zip
69-
mv tlapm-$TLAPS_VERSION deps/tlapm
70-
- name: Download TLA⁺ dependencies
43+
run: $SCRIPT_DIR/windows-setup.sh $SCRIPT_DIR $DEPS_DIR false
44+
- name: Download TLA⁺ dependencies (Linux & macOS)
7145
if: matrix.os != 'windows-latest'
72-
run: |
73-
# Print out tool version information
74-
java --version
75-
python --version
76-
pip --version
77-
cc --version
78-
cpp --version
79-
# Install python packages
80-
pip install -r $SCRIPT_DIR/requirements.txt
81-
# Put all dependencies in their own directory to ensure they aren't included implicitly
82-
mkdir deps
83-
# Get tree-sitter-tlaplus
84-
wget -nv https://github.com/tlaplus-community/tree-sitter-tlaplus/archive/main.tar.gz
85-
tar -xf main.tar.gz
86-
rm main.tar.gz
87-
mv tree-sitter-tlaplus-main deps/tree-sitter-tlaplus
88-
# Get TLA⁺ tools
89-
mkdir deps/tools
90-
wget -nv http://nightly.tlapl.us/dist/tla2tools.jar -O deps/tools/tla2tools.jar
91-
# Get TLA⁺ community modules
92-
mkdir deps/community
93-
wget -nv https://github.com/tlaplus/CommunityModules/releases/latest/download/CommunityModules-deps.jar \
94-
-O deps/community/modules.jar
95-
# Get TLAPS modules
96-
wget -nv https://github.com/tlaplus/tlapm/archive/refs/tags/$TLAPS_VERSION.tar.gz
97-
tar -xf $TLAPS_VERSION.tar.gz
98-
rm $TLAPS_VERSION.tar.gz
99-
mv tlapm-$TLAPS_VERSION deps/tlapm
100-
# Install TLAPS
101-
if [[ "${{ runner.os }}" == "Linux" ]]; then
102-
TLAPM_BIN_TYPE=x86_64-linux-gnu
103-
elif [[ "${{ runner.os }}" == "macOS" ]]; then
104-
TLAPM_BIN_TYPE=i386-darwin
105-
else
106-
echo "Unknown OS"
107-
exit 1
108-
fi
109-
TLAPM_BIN="tlaps-1.5.0-$TLAPM_BIN_TYPE-inst.bin"
110-
wget -nv https://github.com/tlaplus/tlapm/releases/download/$TLAPS_VERSION/$TLAPM_BIN
111-
chmod +x $TLAPM_BIN
112-
# Workaround for https://github.com/tlaplus/tlapm/issues/88
113-
set +e
114-
for ((attempt = 1; attempt <= 5; attempt++)); do
115-
rm -rf deps/tlapm-install
116-
./$TLAPM_BIN -d deps/tlapm-install
117-
if [ $? -eq 0 ]; then
118-
exit 0
119-
fi
120-
done
121-
exit 1
46+
run: $SCRIPT_DIR/linux-setup.sh $SCRIPT_DIR $DEPS_DIR false
12247
- name: Check manifest.json format
12348
run: |
12449
python $SCRIPT_DIR/check_manifest_schema.py \
@@ -133,25 +58,25 @@ jobs:
13358
run: |
13459
python $SCRIPT_DIR/check_manifest_features.py \
13560
--manifest_path manifest.json \
136-
--ts_path deps/tree-sitter-tlaplus
61+
--ts_path $DEPS_DIR/tree-sitter-tlaplus
13762
- name: Check README spec table
13863
run: |
13964
python $SCRIPT_DIR/check_markdown_table.py \
14065
--manifest_path manifest.json \
14166
--readme_path README.md
14267
- name: Parse all modules
14368
run: |
144-
python $SCRIPT_DIR/parse_modules.py \
145-
--tools_jar_path deps/tools/tla2tools.jar \
146-
--tlapm_lib_path deps/tlapm/library \
147-
--community_modules_jar_path deps/community/modules.jar \
69+
python $SCRIPT_DIR/parse_modules.py \
70+
--tools_jar_path $DEPS_DIR/tools/tla2tools.jar \
71+
--tlapm_lib_path $DEPS_DIR/tlapm/library \
72+
--community_modules_jar_path $DEPS_DIR/community/modules.jar \
14873
--manifest_path manifest.json
14974
- name: Check small models
15075
run: |
151-
python $SCRIPT_DIR/check_small_models.py \
152-
--tools_jar_path deps/tools/tla2tools.jar \
153-
--tlapm_lib_path deps/tlapm/library \
154-
--community_modules_jar_path deps/community/modules.jar \
76+
python $SCRIPT_DIR/check_small_models.py \
77+
--tools_jar_path $DEPS_DIR/tools/tla2tools.jar \
78+
--tlapm_lib_path $DEPS_DIR/tlapm/library \
79+
--community_modules_jar_path $DEPS_DIR/community/modules.jar \
15580
--manifest_path manifest.json
15681
- name: Smoke-test large models
15782
run: |
@@ -163,11 +88,11 @@ jobs:
16388
if [[ "${{ runner.os }}" == "Windows" ]]; then
16489
SKIP+=("specifications/ewd426/SimTokenRing.cfg")
16590
fi
166-
python $SCRIPT_DIR/smoke_test_large_models.py \
167-
--tools_jar_path deps/tools/tla2tools.jar \
168-
--tlapm_lib_path deps/tlapm/library \
169-
--community_modules_jar_path deps/community/modules.jar \
170-
--manifest_path manifest.json \
91+
python $SCRIPT_DIR/smoke_test_large_models.py \
92+
--tools_jar_path $DEPS_DIR/tools/tla2tools.jar \
93+
--tlapm_lib_path $DEPS_DIR/tlapm/library \
94+
--community_modules_jar_path $DEPS_DIR/community/modules.jar \
95+
--manifest_path manifest.json \
17196
--skip "${SKIP[@]}"
17297
- name: Check proofs
17398
if: matrix.os != 'windows-latest'
@@ -188,16 +113,16 @@ jobs:
188113
specifications/MisraReachability/ReachabilityProofs.tla
189114
specifications/byzpaxos/BPConProof.tla # Takes about 30 minutes
190115
)
191-
python $SCRIPT_DIR/check_proofs.py \
192-
--tlapm_path deps/tlapm-install \
193-
--manifest_path manifest.json \
116+
python $SCRIPT_DIR/check_proofs.py \
117+
--tlapm_path $DEPS_DIR/tlapm-install \
118+
--manifest_path manifest.json \
194119
--skip "${SKIP[@]}"
195120
- name: Smoke-test manifest generation script
196121
run: |
197-
rm -r deps/tree-sitter-tlaplus/build
122+
rm -r $DEPS_DIR/tree-sitter-tlaplus/build
198123
python $SCRIPT_DIR/generate_manifest.py \
199124
--manifest_path manifest.json \
200125
--ci_ignore_path .ciignore \
201-
--ts_path deps/tree-sitter-tlaplus
126+
--ts_path $DEPS_DIR/tree-sitter-tlaplus
202127
git diff -a
203128

README.md

-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ All specs in this repository are subject to CI validation to ensure quality.
1616

1717
## Examples Included Here
1818
Here is a list of specs included in this repository, with links to the relevant directory and flags for various features:
19-
<<<<<<< HEAD
2019
| Name | Author(s) | Beginner | TLAPS Proof | PlusCal | TLC Model | Apalache |
2120
| --------------------------------------------------------------------------------------------------- | --------------------------------------------------- | :------: | :---------: | :-----: | :-------: | :------: |
2221
| [Teaching Concurrency](specifications/TeachingConcurrency) | Leslie Lamport ||||| |

0 commit comments

Comments
 (0)