Skip to content

Auto-invite on invitation issue #20

Auto-invite on invitation issue

Auto-invite on invitation issue #20

Workflow file for this run

name: "Auto-invite on invitation issue"
on:
issues:
types: [opened]
jobs:
invite:
if: >
contains(github.event.issue.labels.*.name, 'welcome') &&
github.event.issue.title == 'Please invite me to RatLoopz'
runs-on: ubuntu-latest
steps:
- name: Invite user to organization with prepared email
id: invite_user
uses: actions/github-script@v7
with:
github-token: ${{ secrets.ORG_INVITE_TOKEN }}
script: |
// core, github, context are already injected by github-script
const issue = context.payload.issue;
const body = issue.body || '';
function extractUsernameFromBody(text) {
const match = text.match(/###\s*GitHub username\s*\n+([A-Za-z0-9-]+)/i);
return match ? match[1].trim() : null;
}
function extractEmailFromBody(text) {
const match = text.match(/###\s*Email[^\n]*\n+([^\n]+)/i);
return match ? match[1].trim() : null;
}
let username = extractUsernameFromBody(body)
|| issue.user?.login
|| null;
let email = extractEmailFromBody(body);
if (!username) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: "⚠️ Could not determine your GitHub username. Please reply with your GitHub handle."
});
return;
}
try {
const { data: user } = await github.rest.users.getByUsername({ username });
await github.rest.orgs.createInvitation({
org: context.repo.owner,
invitee_id: user.id,
role: 'direct_member'
});
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `✅ Invitation sent to @${username}. Check your email or GitHub notifications.`
});
core.setOutput('email', email || '');
core.setOutput('username', username);
core.setOutput('invite_status', 'invited');
} catch (error) {
if (error.message.includes("Invitee is already a part of this organization")) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `ℹ️ @${username} is already a member of RatLoopz.`
});
core.setOutput('invite_status', 'already_member');
core.setOutput('email', email || '');
core.setOutput('username', username);
return;
}
if (error.message.includes("has already been invited")) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `ℹ️ @${username} already has a pending invite. Check your email or GitHub notifications.`
});
core.setOutput('invite_status', 'pending');
core.setOutput('email', email || '');
core.setOutput('username', username);
return;
}
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body: `❌ Failed to invite @${username}. Error: \`${error.message}\``
});
core.setOutput('invite_status', 'error');
core.setOutput('email', email || '');
core.setOutput('username', username);
core.setFailed(error.message);
}
- name: Send welcome email via Gmail
if: >
steps.invite_user.outputs.email != '' &&
steps.invite_user.outputs.invite_status != 'error'
uses: dawidd6/action-send-mail@v4
with:
server_address: smtp.gmail.com
server_port: 465
secure: true
username: ${{ secrets.MAIL_USERNAME }}
password: ${{ secrets.MAIL_PASSWORD }}
subject: "Your RatLoopz GitHub Invitation"
to: ${{ steps.invite_user.outputs.email }}
from: "${{ secrets.MAIL_FROM_NAME || 'RatLoopz' }} <${{ secrets.MAIL_USERNAME }}>"
html_body: |
<h2>Welcome to RatLoopz 👋</h2>
<p>Hi @${{ steps.invite_user.outputs.username }},</p>
<p>Your invitation to join the <b>RatLoopz</b> GitHub organization has been sent.</p>
<h3>Next steps</h3>
<ol>
<li>Check your email or GitHub notifications and accept the organization invite.</li>
<li>After accepting, visit:<br/>
<b>https://github.com/orgs/RatLoopz/people</b></li>
<li>Find your profile and set its visibility to:<br/>
<b>Public</b></li>
<li>If your profile remains private, others won’t see your membership.</li>
</ol>
<p>Welcome aboard! 🚀</p>
<p><b>The RatLoopz Team</b></p>