Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: CI - The assign/unassign GitHub Action is not working #2529

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 119 additions & 9 deletions .github/workflows/unassign-issue.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Unassign Issues
name: Assign and Unassign Issues

on:
schedule:
Expand All @@ -7,14 +7,124 @@ on:
types: [created]
workflow_dispatch:


env:
DAYS_UNTIL_STALE: 10 # Number of days before marking as stale
ASSIGNED_LABEL: "📍 Assigned"
PINNED_LABEL: "📌 Pinned"
STALE_LABEL: "Stale"

jobs:
assign:
assign_issue:
if: github.event_name == 'issue_comment'
runs-on: ubuntu-latest
steps:
- name: Assign the user or unassign stale assignments
uses: takanome-dev/[email protected]
with:
github_token: '${{ secrets.GITHUB_TOKEN }}'
assigned_label: 📍 Assigned
days_until_unassign: 10
pin_label: 📌 Pinned
- name: Check for /assign-me comment
uses: actions/github-script@v7
with:
script: |
const { owner, repo } = context.repo;
const issue_number = context.issue.number;
const comment = context.payload.comment.body;
const totalDays = process.env.DAYS_UNTIL_STALE;
const assignedLabel = process.env.ASSIGNED_LABEL;
const pinnedLabel = process.env.PINNED_LABEL;

async function addComment(body) {
await github.rest.issues.createComment({ owner, repo, issue_number, body });
}

async function addLabels(labels) {
await github.rest.issues.addLabels({ owner, repo, issue_number, labels });
}

if (comment.includes('/assign-me')) {
try {
// Get the current issue details
const issue = await github.rest.issues.get({ owner, repo, issue_number });

if (issue.data.assignees.length === 0) {
// Issue is not assigned, proceed with assignment
await github.rest.issues.addAssignees({ owner, repo, issue_number, assignees: [context.actor] });

// Add the '📍 Assigned' label to the issue
await addLabels([assignedLabel]);

// Add the custom comment to notify the user of the assignment
const successMessage = `👋 Hey @${context.actor}, thanks for your interest in this issue! 🎉\n\n`
+ `⚠ Note that this issue will become unassigned if it isn't closed within **${totalDays} days**.\n\n`
+ `🔧 A maintainer can also add the **${pinnedLabel}** label to prevent it from being unassigned automatically.`;

await addComment(successMessage);
console.log(`Assigned issue #${issue_number} to ${context.actor}`);
} else {
// Issue is already assigned
const currentAssignee = issue.data.assignees[0].login;
const alreadyAssignedMessage = `👋 Hey @${context.actor}, this issue is already assigned to @${currentAssignee}.\n\n`
+ `⚠️ It will become unassigned if it isn't closed within **${totalDays} days**.\n\n`
+ `🔧 A maintainer can also add you to the list of assignees or swap you with the current assignee.`;

await addComment(alreadyAssignedMessage);
console.log(`Failed to assign issue #${issue_number} to ${context.actor} as it's already assigned to ${currentAssignee}`);
}
} catch (error) {
console.error(`Error assigning issue #${issue_number}: ${error.message}`);
}
}

unassign_stale:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- name: Mark stale issues
uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: "This issue has been automatically unassigned due to inactivity."
days-before-stale: ${{ env.DAYS_UNTIL_STALE }} # Number of days before marking as stale
days-before-close: -1 # Don't close stale issues
exempt-issue-labels: ${{ env.PINNED_LABEL }}
remove-stale-when-updated: false
only-labels: ${{ env.ASSIGNED_LABEL }}

- name: Unassign stale issues and remove labels
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const assignedLabel = process.env.ASSIGNED_LABEL;
const staleLabel = process.env.STALE_LABEL;

async function removeLabel(issue_number, name) {
try {
await github.rest.issues.removeLabel({ owner, repo, issue_number, name });
} catch (error) {
console.log(`Failed to remove ${name} label from issue #${issue_number}: ${error.message}`);
}
}

const staleIssues = await github.paginate(github.rest.issues.listForRepo, {
owner, repo,
state: 'open',
labels: staleLabel,
assignee: '*'
});

for (const issue of staleIssues) {
try {
// Remove assignees
await github.rest.issues.removeAssignees({
owner, repo, issue_number: issue.number,
assignees: issue.assignees.map(a => a.login)
});

// Remove 'Assigned' and 'Stale' labels
await removeLabel(issue.number, assignedLabel);
await removeLabel(issue.number, staleLabel);

console.log(`Unassigned issue #${issue.number}`);
} catch (error) {
console.error(`Error unassigning issue #${issue.number}: ${error.message}`);
}
}
44 changes: 35 additions & 9 deletions exporter/fileexporter/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ func TestFile_Export(t *testing.T) {
args args
wantErr bool
expected expected
setup func(t *testing.T, dir string)
teardown func(t *testing.T, dir string)
setup func(t *testing.T, fields fields)
teardown func(t *testing.T, fields fields)
}{
{
name: "all default json",
Expand Down Expand Up @@ -321,14 +321,40 @@ func TestFile_Export(t *testing.T) {
},
},
},
setup: func(t *testing.T, dir string) {
err := os.MkdirAll(dir, 0755)
setup: func(t *testing.T, fields fields) {
err := os.MkdirAll(fields.OutputDir, 0755)
assert.NoError(t, err)
err = os.Chmod(dir, 0000) // Remove all permissions
err = os.Chmod(fields.OutputDir, 0000) // Remove all permissions
assert.NoError(t, err)
},
teardown: func(t *testing.T, dir string) {
err := os.Chmod(dir, 0755) // Restore permissions for cleanup
teardown: func(t *testing.T, fields fields) {
err := os.Chmod(fields.OutputDir, 0755) // Restore permissions for cleanup
assert.NoError(t, err)
},
},
{
name: "outputdir with invalid parent folder",
wantErr: true,
fields: fields{
Format: "parquet",
OutputDir: filepath.Join(tempDir, "invalid-parent-dir"),
},
args: args{
featureEvents: []exporter.FeatureEvent{
{
Kind: "feature", ContextKind: "anonymousUser", UserKey: "ABCD", CreationDate: 1617970547, Key: "random-key",
Variation: "Default", Value: "YO", Default: false, Source: "SERVER",
},
},
},
setup: func(t *testing.T, fields fields) {
err := os.MkdirAll(tempDir, 0755)
assert.NoError(t, err)
err = os.Chmod(tempDir, 0000) // Remove all permissions
assert.NoError(t, err)
},
teardown: func(t *testing.T, fields fields) {
err := os.Chmod(tempDir, 0755) // Restore permissions for cleanup
assert.NoError(t, err)
},
},
Expand Down Expand Up @@ -366,11 +392,11 @@ func TestFile_Export(t *testing.T) {
}

if tt.setup != nil {
tt.setup(t, outputDir)
tt.setup(t, tt.fields)
}

if tt.teardown != nil {
defer tt.teardown(t, outputDir)
defer tt.teardown(t, tt.fields)
}

f := &fileexporter.Exporter{
Expand Down
Loading