[Bug]: Port change in Docker refused to connect #2862
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: PR Deployment via Comment | |
on: | |
issue_comment: | |
types: [created] | |
permissions: | |
contents: read | |
pull-requests: read | |
jobs: | |
check-comment: | |
runs-on: ubuntu-latest | |
permissions: | |
issues: write | |
if: | | |
github.event.issue.pull_request && | |
( | |
contains(github.event.comment.body, 'prdeploy') || | |
contains(github.event.comment.body, 'deploypr') | |
) | |
&& | |
( | |
github.event.comment.user.login == 'frooodle' || | |
github.event.comment.user.login == 'sf298' || | |
github.event.comment.user.login == 'Ludy87' || | |
github.event.comment.user.login == 'LaserKaspar' || | |
github.event.comment.user.login == 'sbplat' || | |
github.event.comment.user.login == 'reecebrowne' || | |
github.event.comment.user.login == 'DarioGii' || | |
github.event.comment.user.login == 'EthanHealy01' || | |
github.event.comment.user.login == 'ConnorYoh' | |
) | |
outputs: | |
pr_number: ${{ steps.get-pr.outputs.pr_number }} | |
comment_id: ${{ github.event.comment.id }} | |
disable_security: ${{ steps.check-security-flag.outputs.disable_security }} | |
enable_pro: ${{ steps.check-pro-flag.outputs.enable_pro }} | |
enable_enterprise: ${{ steps.check-pro-flag.outputs.enable_enterprise }} | |
steps: | |
- name: Harden Runner | |
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 | |
with: | |
egress-policy: audit | |
- name: Checkout PR | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
- name: Setup GitHub App Bot | |
if: github.actor != 'dependabot[bot]' | |
id: setup-bot | |
uses: ./.github/actions/setup-bot | |
continue-on-error: true | |
with: | |
app-id: ${{ secrets.GH_APP_ID }} | |
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} | |
- name: Get PR data | |
id: get-pr | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
script: | | |
const prNumber = context.payload.issue.number; | |
console.log(`PR Number: ${prNumber}`); | |
core.setOutput('pr_number', prNumber); | |
- name: Check for security/login flag | |
id: check-security-flag | |
env: | |
COMMENT_BODY: ${{ github.event.comment.body }} | |
run: | | |
if [[ "$COMMENT_BODY" == *"security"* ]] || [[ "$COMMENT_BODY" == *"login"* ]]; then | |
echo "Security flags detected in comment" | |
echo "disable_security=false" >> $GITHUB_OUTPUT | |
else | |
echo "No security flags detected in comment" | |
echo "disable_security=true" >> $GITHUB_OUTPUT | |
fi | |
- name: Check for pro flag | |
id: check-pro-flag | |
env: | |
COMMENT_BODY: ${{ github.event.comment.body }} | |
run: | | |
if [[ "$COMMENT_BODY" == *"pro"* ]] || [[ "$COMMENT_BODY" == *"premium"* ]]; then | |
echo "pro flags detected in comment" | |
echo "enable_pro=true" >> $GITHUB_OUTPUT | |
echo "enable_enterprise=false" >> $GITHUB_OUTPUT | |
elif [[ "$COMMENT_BODY" == *"enterprise"* ]]; then | |
echo "enterprise flags detected in comment" | |
echo "enable_enterprise=true" >> $GITHUB_OUTPUT | |
echo "enable_pro=true" >> $GITHUB_OUTPUT | |
else | |
echo "No pro or enterprise flags detected in comment" | |
echo "enable_pro=false" >> $GITHUB_OUTPUT | |
echo "enable_enterprise=false" >> $GITHUB_OUTPUT | |
fi | |
- name: Add 'in_progress' reaction to comment | |
id: add-eyes-reaction | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
github-token: ${{ steps.setup-bot.outputs.token }} | |
script: | | |
console.log(`Adding eyes reaction to comment ID: ${context.payload.comment.id}`); | |
try { | |
const { data: reaction } = await github.rest.reactions.createForIssueComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: context.payload.comment.id, | |
content: 'eyes' | |
}); | |
console.log(`Added reaction with ID: ${reaction.id}`); | |
return { success: true, id: reaction.id }; | |
} catch (error) { | |
console.error(`Failed to add reaction: ${error.message}`); | |
console.error(error); | |
return { success: false, error: error.message }; | |
} | |
deploy-pr: | |
needs: check-comment | |
runs-on: ubuntu-latest | |
permissions: | |
issues: write | |
pull-requests: write | |
steps: | |
- name: Harden Runner | |
uses: step-security/harden-runner@ec9f2d5744a09debf3a187a3f4f675c53b671911 # v2.13.0 | |
with: | |
egress-policy: audit | |
- name: Checkout PR | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
- name: Setup GitHub App Bot | |
if: github.actor != 'dependabot[bot]' | |
id: setup-bot | |
uses: ./.github/actions/setup-bot | |
continue-on-error: true | |
with: | |
app-id: ${{ secrets.GH_APP_ID }} | |
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} | |
- name: Checkout PR | |
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 | |
with: | |
ref: refs/pull/${{ needs.check-comment.outputs.pr_number }}/merge | |
token: ${{ steps.setup-bot.outputs.token }} | |
- name: Set up JDK | |
uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5.0.0 | |
with: | |
java-version: "17" | |
distribution: "temurin" | |
- name: Run Gradle Command | |
run: | | |
if [ "${{ needs.check-comment.outputs.disable_security }}" == "true" ]; then | |
export DISABLE_ADDITIONAL_FEATURES=true | |
else | |
export DISABLE_ADDITIONAL_FEATURES=false | |
fi | |
./gradlew clean build | |
env: | |
STIRLING_PDF_DESKTOP_UI: false | |
- name: Set up Docker Buildx | |
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 | |
- name: Login to Docker Hub | |
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1 # v3.5.0 | |
with: | |
username: ${{ secrets.DOCKER_HUB_USERNAME }} | |
password: ${{ secrets.DOCKER_HUB_API }} | |
- name: Build and push PR-specific image | |
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 | |
with: | |
context: . | |
file: ./Dockerfile | |
push: true | |
tags: ${{ secrets.DOCKER_HUB_USERNAME }}/test:pr-${{ needs.check-comment.outputs.pr_number }} | |
build-args: VERSION_TAG=alpha | |
platforms: linux/amd64 | |
- name: Set up SSH | |
run: | | |
mkdir -p ~/.ssh/ | |
echo "${{ secrets.VPS_SSH_KEY }}" > ../private.key | |
sudo chmod 600 ../private.key | |
- name: Deploy to VPS | |
id: deploy | |
run: | | |
# Set security settings based on flags | |
if [ "${{ needs.check-comment.outputs.disable_security }}" == "false" ]; then | |
DISABLE_ADDITIONAL_FEATURES="false" | |
LOGIN_SECURITY="true" | |
SECURITY_STATUS="🔒 Security Enabled" | |
else | |
DISABLE_ADDITIONAL_FEATURES="true" | |
LOGIN_SECURITY="false" | |
SECURITY_STATUS="Security Disabled" | |
fi | |
# Set pro/enterprise settings (enterprise implies pro) | |
if [ "${{ needs.check-comment.outputs.enable_enterprise }}" == "true" ]; then | |
PREMIUM_ENABLED="true" | |
PREMIUM_KEY="${{ secrets.ENTERPRISE_KEY }}" | |
PREMIUM_PROFEATURES_AUDIT_ENABLED="true" | |
elif [ "${{ needs.check-comment.outputs.enable_pro }}" == "true" ]; then | |
PREMIUM_ENABLED="true" | |
PREMIUM_KEY="${{ secrets.PREMIUM_KEY }}" | |
PREMIUM_PROFEATURES_AUDIT_ENABLED="true" | |
else | |
PREMIUM_ENABLED="false" | |
PREMIUM_KEY="" | |
PREMIUM_PROFEATURES_AUDIT_ENABLED="false" | |
fi | |
# First create the docker-compose content locally | |
cat > docker-compose.yml << EOF | |
version: '3.3' | |
services: | |
stirling-pdf: | |
container_name: stirling-pdf-pr-${{ needs.check-comment.outputs.pr_number }} | |
image: ${{ secrets.DOCKER_HUB_USERNAME }}/test:pr-${{ needs.check-comment.outputs.pr_number }} | |
ports: | |
- "${{ needs.check-comment.outputs.pr_number }}:8080" | |
volumes: | |
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/data:/usr/share/tessdata:rw | |
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/config:/configs:rw | |
- /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/logs:/logs:rw | |
environment: | |
DISABLE_ADDITIONAL_FEATURES: "${DISABLE_ADDITIONAL_FEATURES}" | |
SECURITY_ENABLELOGIN: "${LOGIN_SECURITY}" | |
SYSTEM_DEFAULTLOCALE: en-GB | |
UI_APPNAME: "Stirling-PDF PR#${{ needs.check-comment.outputs.pr_number }}" | |
UI_HOMEDESCRIPTION: "PR#${{ needs.check-comment.outputs.pr_number }} for Stirling-PDF Latest" | |
UI_APPNAMENAVBAR: "PR#${{ needs.check-comment.outputs.pr_number }}" | |
SYSTEM_MAXFILESIZE: "100" | |
METRICS_ENABLED: "true" | |
SYSTEM_GOOGLEVISIBILITY: "false" | |
PREMIUM_KEY: "${PREMIUM_KEY}" | |
PREMIUM_ENABLED: "${PREMIUM_ENABLED}" | |
PREMIUM_PROFEATURES_AUDIT_ENABLED: "${PREMIUM_PROFEATURES_AUDIT_ENABLED}" | |
restart: on-failure:5 | |
EOF | |
# Then copy the file and execute commands | |
scp -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null docker-compose.yml ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }}:/tmp/docker-compose.yml | |
ssh -i ../private.key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -T ${{ secrets.VPS_USERNAME }}@${{ secrets.VPS_HOST }} << ENDSSH | |
# Create PR-specific directories | |
mkdir -p /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/{data,config,logs} | |
# Move docker-compose file to correct location | |
mv /tmp/docker-compose.yml /stirling/PR-${{ needs.check-comment.outputs.pr_number }}/docker-compose.yml | |
# Start or restart the container | |
cd /stirling/PR-${{ needs.check-comment.outputs.pr_number }} | |
docker-compose pull | |
docker-compose up -d | |
ENDSSH | |
# Set output for use in PR comment | |
echo "security_status=${SECURITY_STATUS}" >> $GITHUB_ENV | |
- name: Add success reaction to comment | |
if: success() | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
github-token: ${{ steps.setup-bot.outputs.token }} | |
script: | | |
console.log(`Adding rocket reaction to comment ID: ${{ needs.check-comment.outputs.comment_id }}`); | |
try { | |
const { data: reaction } = await github.rest.reactions.createForIssueComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: ${{ needs.check-comment.outputs.comment_id }}, | |
content: 'rocket' | |
}); | |
console.log(`Added rocket reaction with ID: ${reaction.id}`); | |
} catch (error) { | |
console.error(`Failed to add reaction: ${error.message}`); | |
console.error(error); | |
} | |
// add label to PR | |
const prNumber = ${{ needs.check-comment.outputs.pr_number }}; | |
try { | |
await github.rest.issues.addLabels({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
issue_number: prNumber, | |
labels: ['pr-deployed'] | |
}); | |
console.log(`Added 'pr-deployed' label to PR #${prNumber}`); | |
} catch (error) { | |
console.error(`Failed to add label to PR: ${error.message}`); | |
console.error(error); | |
} | |
- name: Add failure reaction to comment | |
if: failure() | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
github-token: ${{ steps.setup-bot.outputs.token }} | |
script: | | |
console.log(`Adding -1 reaction to comment ID: ${{ needs.check-comment.outputs.comment_id }}`); | |
try { | |
const { data: reaction } = await github.rest.reactions.createForIssueComment({ | |
owner: context.repo.owner, | |
repo: context.repo.repo, | |
comment_id: ${{ needs.check-comment.outputs.comment_id }}, | |
content: '-1' | |
}); | |
console.log(`Added -1 reaction with ID: ${reaction.id}`); | |
} catch (error) { | |
console.error(`Failed to add reaction: ${error.message}`); | |
console.error(error); | |
} | |
- name: Post deployment URL to PR | |
if: success() | |
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 | |
with: | |
github-token: ${{ steps.setup-bot.outputs.token }} | |
script: | | |
const { GITHUB_REPOSITORY } = process.env; | |
const [repoOwner, repoName] = GITHUB_REPOSITORY.split('/'); | |
const prNumber = ${{ needs.check-comment.outputs.pr_number }}; | |
const securityStatus = process.env.security_status || "Security Disabled"; | |
const deploymentUrl = `http://${{ secrets.VPS_HOST }}:${prNumber}`; | |
const commentBody = `## 🚀 PR Test Deployment\n\n` + | |
`Your PR has been deployed for testing!\n\n` + | |
`🔗 **Test URL:** [${deploymentUrl}](${deploymentUrl})\n` + | |
`${securityStatus}\n\n` + | |
`This deployment will be automatically cleaned up when the PR is closed.\n\n`; | |
await github.rest.issues.createComment({ | |
owner: repoOwner, | |
repo: repoName, | |
issue_number: prNumber, | |
body: commentBody | |
}); | |
- name: Cleanup temporary files | |
if: always() | |
run: | | |
echo "Cleaning up temporary files..." | |
rm -f ../private.key docker-compose.yml | |
echo "Cleanup complete." | |
continue-on-error: true |