1212 required : true
1313 type : string
1414 default : " 2.0.0-rc.16"
15+ deploy_tags :
16+ description : " Ansible tags to run. Use full_deploy for full flow, or a narrower tag such as unban_hp_masternodes to resume faster."
17+ required : true
18+ type : string
19+ default : " full_deploy"
1520 # Advanced options - sane defaults, only change if you know what you're doing
1621 hp_masternodes_arm_count :
1722 description : " Advanced: Number of ARM HP masternodes"
5257jobs :
5358 create :
5459 name : Create Devnet
55- runs-on : ubuntu-latest
60+ runs-on : ubuntu-22.04
5661 timeout-minutes : 120
5762 concurrency :
5863 group : " devnet-${{ github.event.inputs.devnet_name }}"
5964 cancel-in-progress : false
6065
6166 env :
6267 NETWORK_NAME : " devnet-${{ github.event.inputs.devnet_name }}"
68+ DEVNET_ONLY_GUARD : " true"
6369 AWS_ACCESS_KEY_ID : ${{ secrets.AWS_ACCESS_KEY_ID }}
6470 AWS_SECRET_ACCESS_KEY : ${{ secrets.AWS_SECRET_ACCESS_KEY }}
6571 AWS_REGION : ${{ secrets.AWS_REGION }}
8591 echo "Error: devnet_name must be lowercase alphanumeric with optional hyphens"
8692 exit 1
8793 fi
94+ if [[ "$NAME" == "testnet" || "$NAME" == "mainnet" || "$NAME" == mainnet-* ]]; then
95+ echo "Error: reserved network names are not allowed in this workflow"
96+ exit 1
97+ fi
98+ if [[ ! "devnet-$NAME" =~ ^devnet-[a-z0-9][a-z0-9-]*$ ]]; then
99+ echo "Error: resulting network name is not a valid devnet name"
100+ exit 1
101+ fi
88102 echo "Will create: devnet-$NAME"
89103
90104 - name : Checkout dash-network-deploy
@@ -112,7 +126,7 @@ jobs:
112126 - name : Install Ansible
113127 run : |
114128 python3 -m pip install --upgrade pip
115- python3 -m pip install ansible
129+ python3 -m pip install ansible-core==2.16.3 jmespath
116130
117131 - name : Install Ansible roles
118132 run : |
@@ -124,6 +138,7 @@ jobs:
124138 env :
125139 DEPLOY_SERVER_KEY : ${{ secrets.DEPLOY_SERVER_KEY }}
126140 EVO_APP_DEPLOY_KEY : ${{ secrets.EVO_APP_DEPLOY_KEY }}
141+ EVO_APP_DEPLOY_WRITE_KEY : ${{ secrets.EVO_APP_DEPLOY_WRITE_KEY }}
127142 run : |
128143 mkdir -p ~/.ssh
129144
@@ -139,6 +154,12 @@ jobs:
139154 printf '%s\n' "$EVO_APP_DEPLOY_KEY" > ~/.ssh/id_ed25519
140155 chmod 600 ~/.ssh/id_ed25519
141156
157+ # Optional write key for pushing to configs repo
158+ if [[ -n "$EVO_APP_DEPLOY_WRITE_KEY" ]]; then
159+ printf '%s\n' "$EVO_APP_DEPLOY_WRITE_KEY" > ~/.ssh/id_ed25519_write
160+ chmod 600 ~/.ssh/id_ed25519_write
161+ fi
162+
142163 # SSH config
143164 cat > ~/.ssh/config << 'EOL'
144165 Host github.com
@@ -168,7 +189,39 @@ jobs:
168189 TERRAFORM_DYNAMODB_TABLE=$TERRAFORM_DYNAMODB_TABLE
169190 EOF
170191
192+ - name : Check for existing devnet configs
193+ id : existing_configs
194+ run : |
195+ git clone git@github.com:dashpay/dash-network-configs.git /tmp/dash-network-configs-source
196+
197+ FOUND=0
198+ MISSING=0
199+ for ext in yml tfvars inventory; do
200+ SRC="/tmp/dash-network-configs-source/$NETWORK_NAME.$ext"
201+ if [[ -f "$SRC" ]]; then
202+ FOUND=$((FOUND + 1))
203+ else
204+ MISSING=$((MISSING + 1))
205+ fi
206+ done
207+
208+ if [[ $FOUND -eq 3 ]]; then
209+ echo "resume_mode=true" >> "$GITHUB_OUTPUT"
210+ echo "Found existing config set for $NETWORK_NAME. Reusing config repo files and skipping Terraform."
211+ cp "/tmp/dash-network-configs-source/$NETWORK_NAME.yml" networks/
212+ cp "/tmp/dash-network-configs-source/$NETWORK_NAME.tfvars" networks/
213+ cp "/tmp/dash-network-configs-source/$NETWORK_NAME.inventory" networks/
214+ elif [[ $FOUND -eq 0 ]]; then
215+ echo "resume_mode=false" >> "$GITHUB_OUTPUT"
216+ echo "No existing config set found for $NETWORK_NAME. Running full create flow."
217+ else
218+ echo "Error: Partial config set found for $NETWORK_NAME in dash-network-configs."
219+ ls -la /tmp/dash-network-configs-source/$NETWORK_NAME.* 2>/dev/null || true
220+ exit 1
221+ fi
222+
171223 - name : Generate network configs
224+ if : steps.existing_configs.outputs.resume_mode != 'true'
172225 env :
173226 MN_AMD : ${{ github.event.inputs.masternodes_amd_count }}
174227 MN_ARM : ${{ github.event.inputs.masternodes_arm_count }}
@@ -236,9 +289,21 @@ jobs:
236289 DISK_SIZE : ${{ github.event.inputs.hpmn_disk_size }}
237290 run : |
238291 TFVARS_FILE="networks/$NETWORK_NAME.tfvars"
292+ DEFAULT_MAIN_DOMAIN="networks.dash.org"
239293
240294 # Read current value from file (empty if not set)
241295 CURRENT_SIZE=$(grep -oP 'hpmn_node_disk_size\s*=\s*\K[0-9]+' "$TFVARS_FILE" 2>/dev/null || echo "")
296+ CURRENT_MAIN_DOMAIN=$(grep -oP 'main_domain\s*=\s*"\K[^"]*' "$TFVARS_FILE" 2>/dev/null || echo "")
297+
298+ # Generated tfvars leaves main_domain empty; ensure ACM DNS names are valid.
299+ if [[ -z "$CURRENT_MAIN_DOMAIN" ]]; then
300+ echo "Setting main_domain to $DEFAULT_MAIN_DOMAIN..."
301+ if grep -q '^main_domain\s*=' "$TFVARS_FILE"; then
302+ sed -i "s|^main_domain\\s*=.*|main_domain = \"$DEFAULT_MAIN_DOMAIN\"|" "$TFVARS_FILE"
303+ else
304+ echo "main_domain = \"$DEFAULT_MAIN_DOMAIN\"" >> "$TFVARS_FILE"
305+ fi
306+ fi
242307
243308 if [[ -n "$DISK_SIZE" && "$DISK_SIZE" != "$CURRENT_SIZE" ]]; then
244309 if [[ ! "$DISK_SIZE" =~ ^[0-9]+$ ]]; then
@@ -257,32 +322,69 @@ jobs:
257322 cat "$TFVARS_FILE"
258323
259324 - name : Deploy devnet (Terraform + Ansible)
325+ env :
326+ TF_IN_AUTOMATION : " true"
327+ TF_CLI_ARGS_apply : " -auto-approve"
328+ DEPLOY_TAGS : ${{ github.event.inputs.deploy_tags }}
260329 run : |
261330 echo "============================================"
262331 echo "Deploying $NETWORK_NAME"
332+ echo "Ansible tags: $DEPLOY_TAGS"
263333 echo "============================================"
264334
265335 chmod +x ./bin/deploy
266336 # GitHub Actions checks out a detached HEAD; bypass branch safety check.
267- ./bin/deploy -f "$NETWORK_NAME"
337+ if [[ "${{ steps.existing_configs.outputs.resume_mode }}" == "true" ]]; then
338+ echo "Resume mode enabled. Skipping Terraform and re-running provisioning only."
339+ ./bin/deploy -p -f --tags="$DEPLOY_TAGS" "$NETWORK_NAME"
340+ else
341+ ./bin/deploy -f --tags="$DEPLOY_TAGS" "$NETWORK_NAME"
342+ fi
268343
269344 - name : Push configs to dash-network-configs
345+ if : always()
346+ env :
347+ EVO_APP_DEPLOY_WRITE_KEY : ${{ secrets.EVO_APP_DEPLOY_WRITE_KEY }}
270348 run : |
271349 # Clone the configs repo to a temp directory
272350 git clone git@github.com:dashpay/dash-network-configs.git /tmp/dash-network-configs
273351
274- # Copy generated config files
275- cp "networks/$NETWORK_NAME.yml" /tmp/dash-network-configs/
276- cp "networks/$NETWORK_NAME.tfvars" /tmp/dash-network-configs/
277- cp "networks/$NETWORK_NAME.inventory" /tmp/dash-network-configs/
352+ # Copy generated config files if present
353+ COPIED=0
354+ for ext in yml tfvars inventory; do
355+ SRC="networks/$NETWORK_NAME.$ext"
356+ if [[ -f "$SRC" ]]; then
357+ cp "$SRC" /tmp/dash-network-configs/
358+ COPIED=$((COPIED + 1))
359+ else
360+ echo "Skipping missing file: $SRC"
361+ fi
362+ done
363+
364+ if [[ $COPIED -eq 0 ]]; then
365+ echo "No config files found to push"
366+ exit 0
367+ fi
278368
279369 # Commit and push
280370 cd /tmp/dash-network-configs
281371 git config user.name "GitHub Actions"
282372 git config user.email "actions@github.com"
283373 git add .
284374 git commit -m "Add configs for $NETWORK_NAME" || echo "No changes to commit"
285- git push
375+
376+ # Use optional write key if configured; otherwise try default key.
377+ if [[ -n "$EVO_APP_DEPLOY_WRITE_KEY" && -f "$HOME/.ssh/id_ed25519_write" ]]; then
378+ GIT_SSH_COMMAND='ssh -i ~/.ssh/id_ed25519_write -o StrictHostKeyChecking=no' git push || {
379+ echo "::warning::Failed to push configs with EVO_APP_DEPLOY_WRITE_KEY"
380+ exit 0
381+ }
382+ else
383+ git push || {
384+ echo "::warning::Failed to push configs (likely read-only EVO_APP_DEPLOY_KEY). Configure secret EVO_APP_DEPLOY_WRITE_KEY with write access."
385+ exit 0
386+ }
387+ fi
286388
287389 echo "Configs pushed to dash-network-configs repo"
288390
0 commit comments