Skip to content

Commit c5261f0

Browse files
authored
Multiplatform builds (#36)
### What kind of change does this PR introduce? * Adds builds that do not compile with NetCDF to the main workflows * Substitutes the GitHub Actions tags for commit hashes * Adds the `step-security/harden-runner` action for reducing the attack surface of builds * Adds macOS and Windows builds (macOS with and without NetCDF4) * Adjusts the CMakeLists.txt to emit fewer warnings ### Does this PR introduce a breaking change? <!-- If so, please describe the impact and migration path for existing applications --> No. ### Other information: <!-- Any other information that is of relevance to this PR, such as screenshots or references to external documentation. --> The commit hashes will be managed by Dependabot once that integration has been added to the repository.
1 parent 38cf4df commit c5261f0

20 files changed

+230
-110
lines changed

.github/workflows/first_pull_request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
name: Welcome
1111
runs-on: ubuntu-latest
1212
steps:
13-
- uses: actions/github-script@v6
13+
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
1414
with:
1515
script: |
1616
// Get a list of all issues created by the PR opener

.github/workflows/testing.yml

Lines changed: 130 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -15,48 +15,146 @@ jobs:
1515
run:
1616
shell: bash
1717
steps:
18-
- name: Checkout
19-
uses: actions/checkout@v4
18+
- name: Harden Runner
19+
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
20+
with:
21+
disable-sudo: false
22+
egress-policy: block
23+
allowed-endpoints: >
24+
azure.archive.ubuntu.com:80
25+
esm.ubuntu.com:443
26+
files.pythonhosted.org:443
27+
github.com:443
28+
motd.ubuntu.com:443
29+
packages.microsoft.com:443
30+
pypi.org:443
31+
32+
- name: Checkout Repository
33+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
34+
with:
35+
persist-credentials: false
36+
2037
- name: Install linters
2138
run: |
2239
sudo apt-get update
2340
sudo apt-get install uncrustify cppcheck iwyu
24-
- uses: actions/setup-python@v4
25-
- name: Install pre-commit
41+
42+
- name: Set up Python3
43+
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
44+
with:
45+
python-version: '3.x'
46+
47+
- name: Run pre-commit hooks
48+
uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
49+
50+
build-netcdf:
51+
name: Build (${{ matrix.build_type }}; ${{ matrix.os }}; NetCDF=True)
52+
needs: lint
53+
runs-on: ${{ matrix.os }}
54+
strategy:
55+
fail-fast: false
56+
matrix:
57+
os: [ "ubuntu-latest", "macos-latest" ]
58+
build_type: [ "Debug", "Release" ]
59+
steps:
60+
- name: Harden Runner
61+
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
62+
with:
63+
disable-sudo: false
64+
egress-policy: block
65+
allowed-endpoints: >
66+
azure.archive.ubuntu.com:80
67+
esm.ubuntu.com:443
68+
github.com:443
69+
motd.ubuntu.com:443
70+
packages.microsoft.com:443
71+
raw.githubusercontent.com:443
72+
73+
- name: Checkout Repository
74+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
75+
with:
76+
persist-credentials: false
77+
78+
- name: Install NetCDF (Ubuntu/apt)
79+
if: matrix.os == 'ubuntu-latest'
2680
run: |
27-
python -m pip install --upgrade pip
28-
python -m pip install pre-commit
29-
- name: Run pre-commit
81+
sudo apt-get update
82+
sudo apt-get install -y libnetcdf-dev
83+
- name: Install NetCDF4 (macOS/homebrew)
84+
if: (matrix.os == 'macos-latest') && (!matrix.conda)
85+
uses: tecolicom/actions-use-homebrew-tools@b9c066b79607fa3d71e0be05d7003bb75fd9ff34 # v1.3.0
86+
with:
87+
tools: netcdf
88+
cache: "yes"
89+
90+
- name: Fetch NetCDF CMake script
3091
run: |
31-
pre-commit run --all-files
92+
wget https://raw.githubusercontent.com/Kitware/VTK/master/CMake/FindNetCDF.cmake -P cmake
93+
94+
- name: Build
95+
id: build
96+
run: |
97+
mkdir build
98+
cd build
99+
cmake ..
100+
cmake --build . --config ${{ matrix.build_type }} -j 3 --verbose
101+
102+
- name: Run tests
103+
if: steps.build.outcome == 'success'
104+
run: |
105+
./build/Raven
106+
./build/Raven -v
32107
33108
build:
34-
name: Build RavenHydroFramework binary (${{ matrix.build_type }})
35-
runs-on: ubuntu-latest
109+
name: Build (${{ matrix.build_type }}; ${{ matrix.os }}; NetCDF=False)
110+
needs: lint
111+
runs-on: ${{ matrix.os }}
36112
strategy:
113+
fail-fast: false
37114
matrix:
38-
build_type: [Debug, Release]
115+
os: [ ubuntu-latest, macos-latest, windows-latest ]
116+
build_type: [ Debug, Release ]
39117
defaults:
40118
run:
41-
shell: bash
119+
shell: bash -l {0}
42120
steps:
43-
- name: Checkout
44-
uses: actions/checkout@v4
45-
- name: Install dependencies
46-
run: |
47-
sudo apt-get update
48-
sudo apt-get install libnetcdf-dev build-essential cmake
49-
- name: Fetch NetCDF CMake script
50-
run: |
51-
wget https://raw.githubusercontent.com/Kitware/VTK/master/CMake/FindNetCDF.cmake -P cmake
52-
- name: Build
53-
id: build
54-
continue-on-error: true
55-
run: |
56-
cmake . -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
57-
make -j4
58-
- name: Run tests
59-
if: steps.build.outcome == 'success'
60-
run: |
61-
./Raven
62-
./Raven -v
121+
- name: Harden Runner
122+
uses: step-security/harden-runner@17d0e2bd7d51742c71671bd19fa12bdc9d40a3d6 # v2.8.1
123+
with:
124+
disable-sudo: true
125+
egress-policy: block
126+
allowed-endpoints: >
127+
azure.archive.ubuntu.com:80
128+
esm.ubuntu.com:443
129+
github.com:443
130+
motd.ubuntu.com:443
131+
objects.githubusercontent.com:443
132+
packages.microsoft.com:443
133+
134+
- name: Checkout Repository
135+
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
136+
with:
137+
persist-credentials: false
138+
139+
- name: Install dependencies (Windows)
140+
if: matrix.os == 'windows-latest'
141+
uses: lukka/get-cmake@2bcb1a4c14ab154443cc740dced0f9b6a8fb2b59 # v3.29.6
142+
143+
- name: Build
144+
id: build
145+
run: |
146+
mkdir build
147+
cd build
148+
cmake ..
149+
cmake --build . --config ${{ matrix.build_type }} -j 3 --verbose
150+
151+
- name: Run tests (Windows)
152+
if: ${{ matrix.os == 'windows-latest' && steps.build.outcome == 'success' }}
153+
run: |
154+
./build/${{ matrix.build_type }}/Raven.exe
155+
./build/${{ matrix.build_type }}/Raven.exe -v
156+
- name: Run tests (Ubuntu/macOS)
157+
if: ${{ matrix.os != 'windows-latest' && steps.build.outcome == 'success' }}
158+
run: |
159+
./build/Raven
160+
./build/Raven -v

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,6 @@ Makefile
4141
# Runtime artifacts
4242
Raven
4343
Raven_errors.txt
44+
45+
# JetBrains
46+
.idea

CMakeLists.txt

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
cmake_minimum_required(VERSION 3.20)
22
# made with help from Zhu Liang-Jun of IGSNRR in Beijing
3-
# modified for GitHub by Trevor James Smith of Ouranos in Montreal
3+
# modified for GitHub and C++11 by Trevor James Smith of Ouranos in Montreal
44
# modified for lpsolve support by Maxim Krassovski of DFO
55

6+
# Set the C++ standard to C++11
7+
set(CMAKE_CXX_STANDARD 11)
8+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
9+
SET(CMAKE_CXX_EXTENSIONS OFF)
10+
611
# optional cmake command line arguments (e.g, "cmake -D COMPILE_LIB=ON" .)
712
option(COMPILE_LIB "If ON, will create a dynamic lib file (default: OFF)" OFF)
813
option(COMPILE_EXE "If ON, will create a executable file (default: ON)" ON)
914
option(PYTHON, "If ON, will create a share library for python (default: OFF)" OFF)
10-
option(LPSOLVE,"If ON, will link to lp_solve optimization library (default: OFF)" OFF)
15+
option(LPSOLVE, "If ON, will link to lp_solve optimization library (default: OFF)" OFF)
1116

1217
# Setup Project
1318
PROJECT(Raven CXX)
@@ -17,7 +22,14 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
1722

1823
# Find NetCDF
1924
find_package(NetCDF) #may also be 'netCDF'
20-
find_package(netCDF)
25+
if (NOT NetCDF_FOUND)
26+
message(STATUS "NetCDF not found, trying netCDF")
27+
find_package(netCDF)
28+
endif()
29+
30+
# Find HDF5
31+
find_package(HDF5)
32+
2133
# find header & source
2234
file(GLOB HEADER "src/*.h")
2335
file(GLOB SOURCE "src/*.cpp")
@@ -45,18 +57,21 @@ if(COMPILE_EXE)
4557
${SOURCE}
4658
${HEADER}
4759
)
48-
target_compile_definitions(Raven PUBLIC STANDALONE)
4960
set_target_properties(Raven PROPERTIES LINKER_LANGUAGE CXX)
61+
62+
# Remove deprecation warnings for GCC
63+
IF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
64+
target_compile_options(Raven PRIVATE "-Wno-deprecated")
65+
message(STATUS "Modified compile flags with '-Wno-deprecated'")
66+
ENDIF()
67+
5068
if(LPSOLVE)
5169
target_link_directories(Raven PRIVATE lib/lp_solve) # where liblpsolve55.so is located
5270
target_link_libraries(Raven lpsolve55)
5371
add_definitions(-D_LPSOLVE_)
5472
endif()
5573
endif()
5674

57-
source_group("Header Files" FILES ${HEADER})
58-
source_group("Source Files" FILES ${SOURCE})
59-
6075
if(NETCDF_FOUND)
6176
add_definitions(-Dnetcdf)
6277
include_directories(${NetCDF_INCLUDE_DIRS})
@@ -67,6 +82,9 @@ elseif(netCDF_FOUND)
6782
target_link_libraries(Raven netcdf)
6883
endif()
6984

85+
source_group("Header Files" FILES ${HEADER})
86+
source_group("Source Files" FILES ${SOURCE})
87+
7088
# unset cmake variables to avoid polluting the cache
7189
unset(COMPILE_LIB CACHE)
7290
unset(COMPILE_EXE CACHE)

src/Assimilate.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ void CModel::PrepareAssimilation(const optStruct &Options,const time_struct &tt)
170170
_aDAoverride [p]=true;
171171
_aDAobsQ [p]=Qobs;
172172
_aDADrainSum [p]=0.0; //??? maybe doesnt matter
173-
if (pdown != DOESNT_EXIST) {
173+
if (pdown != DOESNT_EXIST) {
174174
_aDADrainSum [pdown]+=_pSubBasins[p]->GetDrainageArea(); //DOES THIS HANDLE NESTING RIGHT?
175175
}
176176
}
@@ -182,17 +182,17 @@ void CModel::PrepareAssimilation(const optStruct &Options,const time_struct &tt)
182182
_aDAlength [p]=0.0;
183183
_aDAoverride [p]=false;
184184
_aDAobsQ [p]=0.0;
185-
if (pdown != DOESNT_EXIST) {
185+
if (pdown != DOESNT_EXIST) {
186186
_aDADrainSum[pdown] += _aDADrainSum[p];
187187
}
188188
}
189189
ObsExists=true;
190190
break; //avoids duplicate observations
191191
}
192192
}
193-
}
193+
}
194194
else {
195-
if (pdown != DOESNT_EXIST) {
195+
if (pdown != DOESNT_EXIST) {
196196
_aDADrainSum[pdown] += _aDADrainSum[p];
197197
}
198198
}

src/DemandExpressionHandling.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -958,13 +958,13 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s,
958958
return tmp;
959959
}
960960
//////////////////////////////////////////////////////////////////
961-
/// \brief Parses :Condition within management goal or workflow variable definition
961+
/// \brief Parses :Condition within management goal or workflow variable definition
962962
/// \param s [in] - array of strings of [size: Len]
963963
/// \param Len [in] - length of string array
964964
/// \param lineno [in] - line number of original expression in input file filename, referenced in errors
965965
/// \param filename [in] - name of input file, referenced in errors
966966
/// \returns exp_condition: a pointer to an expression condition variable
967-
///
967+
///
968968
/// \todo[funct]: Would it be better to support @date(), @between, @day_of_year() in general expression??
969969
/// :Condition !Q32[0] < 300 + @ts(myTs,0)
970970
/// :Condition DATE IS_BETWEEN 1975-01-02 and 2010-01-02
@@ -978,13 +978,13 @@ expressionStruct *CDemandOptimizer::ParseExpression(const char **s,
978978
/// :Condition DAY_OF_YEAR IS_BETWEEN Apr-1 Aug-1 //\todo [NOT YET SUPPORTED]
979979
/// :Condition @is_between(DAY_OF_YEAR,300,20) = 1 // \todo [NOT YET SUPPORTED]
980980
//
981-
exp_condition* CDemandOptimizer::ParseCondition(const char** s, const int Len, const int lineno, const string filename) const
981+
exp_condition* CDemandOptimizer::ParseCondition(const char** s, const int Len, const int lineno, const string filename) const
982982
{
983983
bool badcond=false;
984984
exp_condition *pCond = new exp_condition();
985985
pCond->dv_name=s[1];
986986
const optStruct *Options=_pModel->GetOptStruct();
987-
987+
988988
bool is_exp=false;
989989
for (int i = 2; i < Len; i++) {
990990
if ((s[i][0]=='+') || (s[i][0]=='-') || (s[i][0]=='*') || (s[i][0]=='/') || (s[i][0]=='=') || (s[i][0]=='<') || (s[i][0]=='>')){
@@ -1021,7 +1021,7 @@ exp_condition* CDemandOptimizer::ParseCondition(const char** s, const int Len, c
10211021
char tmp =pCond->dv_name[1];
10221022
string tmp2=pCond->dv_name.substr(2);
10231023
char code=pCond->dv_name[1];
1024-
if ((code=='Q') || (code=='h') || (code=='I')) //subbasin state decision variable
1024+
if ((code=='Q') || (code=='h') || (code=='I')) //subbasin state decision variable
10251025
{
10261026
long long SBID=s_to_ll(tmp2.c_str());
10271027
if (_pModel->GetSubBasinByID(SBID) == NULL) {
@@ -1147,7 +1147,7 @@ bool CDemandOptimizer::CheckOpRegimeConditions(const op_regime *pOperRegime, con
11471147
}
11481148
else {//handle user specified DVs and workflow variables
11491149
int i=GetUserDVIndex(pCond->dv_name);
1150-
if (i != DOESNT_EXIST) //decision variable
1150+
if (i != DOESNT_EXIST) //decision variable
11511151
{
11521152
dv_value =_pDecisionVars[i]->value;
11531153
}

src/DemandOptimization.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ void CDemandOptimizer::AddUserDecisionVar(const decision_var* pDV)
320320
//////////////////////////////////////////////////////////////////
321321
/// \brief disables stage discharge curve handling for reservoir in subbasin p
322322
//
323-
void CDemandOptimizer::OverrideSDCurve(const int p)
323+
void CDemandOptimizer::OverrideSDCurve(const int p)
324324
{
325325
_aDisableSDCurve[p]=true;
326326
}
@@ -424,7 +424,7 @@ bool CDemandOptimizer::VariableNameExists(const string &name) const
424424
for (int i = 0; i < _nUserConstants; i++) {
425425
if (_aUserConstNames[i]==name){return true;}
426426
}
427-
427+
428428
if (GetUnitConversion(name)!=RAV_BLANK_DATA){return true;}
429429

430430
return false;
@@ -890,7 +890,7 @@ void CDemandOptimizer::InitializePostRVMRead(CModel* pModel, const optStruct& Op
890890
cout<<" "<<i<<" [WORKFLOWVAR]: "<<_pWorkflowVars[i]->name<<endl;
891891
for (int k=0; k<_pWorkflowVars[i]->nOperRegimes; k++)
892892
{
893-
893+
894894
cout<<" +oper regime: "<<_pWorkflowVars[i]->pOperRegimes[k]->reg_name<<endl;
895895
cout<<" +expression: "<<_pWorkflowVars[i]->pOperRegimes[k]->pExpression->origexp<<endl;
896896
comparison ctype=_pWorkflowVars[i]->pOperRegimes[k]->pExpression->compare;
@@ -1644,7 +1644,7 @@ void CDemandOptimizer::SolveDemandProblem(CModel *pModel, const optStruct &Optio
16441644
retval = lp_lib::add_constraintex(pLinProg,i,row_val,col_ind,ROWTYPE_EQ,RHS);
16451645
ExitGracefullyIf(retval==0,"SolveDemandProblem::Error adding mass balance constraint",RUNTIME_ERR);
16461646
IncrementAndSetRowName(pLinProg,rowcount,"reach_MB_"+to_string(pSB->GetID()));
1647-
1647+
16481648
lpsbrow[p]=lp_lib::get_Nrows(pLinProg);
16491649
}
16501650
}

src/DemandOptimization.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,7 @@ class CDemandOptimizer
302302
void OverrideSDCurve (const int p);
303303

304304
void AddGoalOrConstraint (const managementGoal *pGoal);
305-
305+
306306
void AddUserDecisionVar (const decision_var *pDV);
307307
void SetUserDecisionVarBounds(const string name, const double &min, const double &max);
308308
void AddUserConstant (const string name, const double &val);

0 commit comments

Comments
 (0)