Skip to content

chore(deps): update docker.elastic.co/elasticsearch/elasticsearch docker tag to v9.3.4 #4715

chore(deps): update docker.elastic.co/elasticsearch/elasticsearch docker tag to v9.3.4

chore(deps): update docker.elastic.co/elasticsearch/elasticsearch docker tag to v9.3.4 #4715

Workflow file for this run

name: Assign PRs to GitHub Projects V2
on:
pull_request:
types: [opened, reopened, labeled, unlabeled, synchronize]
workflow_dispatch:
inputs:
dry_run:
description: "Ne rien modifier, seulement logguer"
required: false
type: boolean
default: false
env:
PROJECT_ID_MAPPING: |
squad:pmo=PVT_kwDOBOJOp84A8tDc
squad:ux=PVT_kwDOBOJOp84A2ZQ8
squad:backend=PVT_kwDOBOJOp84A2ZRZ
squad:platform=PVT_kwDOBOJOp84BB-GS
IF_UNMATCH: PVT_kwDOBOJOp84A8tDc
# Laisser vide pour ne filtrer par auteur
FILTER_AUTHOR: "renovate[bot]"
jobs:
assign:
if: >
github.event_name == 'workflow_dispatch' ||
(github.event_name == 'pull_request' &&
github.event.pull_request.user.login == 'renovate[bot]')
runs-on: ubuntu-latest
steps:
- name: Assign PRs to Projects
uses: actions/github-script@v9
with:
github-token: ${{ secrets.PROJECT_PAT }}
script: |
const mapping = Object.fromEntries(
(process.env.PROJECT_ID_MAPPING || '')
.split('\n')
.map(l => l.trim().split('='))
.filter(parts => parts.length === 2)
.map(([k, v]) => [k.toLowerCase(), v.trim()])
);
const fallback = (process.env.IF_UNMATCH || '').trim();
const filterAuthor = (process.env.FILTER_AUTHOR || '').trim();
const dryRun = core.getInput('dry_run') === 'true';
// --- Validation des ProjectV2 IDs ---
const allIds = Array.from(
new Set([ ...Object.values(mapping), fallback ].filter(Boolean))
);
if (allIds.length) {
const res = await github.graphql(
`query($ids:[ID!]!){ nodes(ids:$ids){ __typename }}`, { ids: allIds }
);
const invalid = allIds.filter((id, i) => res.nodes[i]?.__typename !== 'ProjectV2');
if (invalid.length) {
core.setFailed('Project IDs introuvables: ' + invalid.join(', '));
return;
}
}
// --- Helpers GraphQL ---
async function getItems(nodeId) {
const q = `
query($id:ID!){ node(id:$id){ ... on PullRequest {
projectItems(first:100){ nodes{id project{id}} }
}}}`;
const r = await github.graphql(q, { id: nodeId });
return r.node.projectItems.nodes.map(n => ({
itemId: n.id,
projectId: n.project.id
}));
}
async function addItem(nodeId, projId) {
const m = `
mutation($projId:ID!,$cntId:ID!){
addProjectV2ItemById(input:{projectId:$projId,contentId:$cntId}) {
item{id}
}
}`;
await github.graphql(m, { projId, cntId: nodeId });
}
async function removeItem(itemId, projId) {
const m = `
mutation($projId:ID!,$itmId:ID!){
deleteProjectV2Item(input:{projectId:$projId,itemId:$itmId}) {
deletedItemId
}
}`;
await github.graphql(m, { projId, itmId: itemId });
}
// --- Calcul des projets cibles ---
function pickProjects(labels) {
const s = new Set();
labels.forEach(l => {
const key = l.toLowerCase();
if (mapping[key]) s.add(mapping[key]);
});
if (!s.size && fallback) s.add(fallback);
return Array.from(s);
}
// --- Construction de la liste des PR à traiter ---
let prNumbers = [];
if (context.eventName === 'workflow_dispatch') {
let page = 1;
while (true) {
const list = await github.rest.pulls.list({
owner: context.repo.owner,
repo: context.repo.repo,
state: 'open',
per_page: 100,
page
});
if (!list.data.length) break;
prNumbers.push(...list.data.map(p => p.number));
page++;
}
} else {
prNumbers = [ context.payload.pull_request.number ];
}
core.info('Processing ' + prNumbers.length + ' PR(s)');
// --- Traitement de chaque PR ---
for (const num of prNumbers) {
core.startGroup('PR #' + num);
// Récupération de la PR
const pr = (context.eventName === 'workflow_dispatch')
? (await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: num
})).data
: context.payload.pull_request;
// Filtre sur l’auteur (uniquement si FILTER_AUTHOR est non vide)
if (filterAuthor !== '' && pr.user.login !== filterAuthor) {
core.info('Auteur ignoré: ' + pr.user.login);
core.endGroup();
continue;
}
// Labels
const labels = pr.labels
.map(l => typeof l === 'string' ? l : l.name)
.map(n => n.toLowerCase());
core.info('Labels: ' + (labels.length ? labels.join(', ') : '(none)'));
// Différences
const desired = pickProjects(labels);
const existing = await getItems(pr.node_id);
const existIds = existing.map(e => e.projectId);
const toAdd = desired.filter(id => !existIds.includes(id));
const toRemove = existing.filter(e => !desired.includes(e.projectId));
core.info('To add: ' + (toAdd .length ? toAdd .join(', ') : '(none)'));
core.info('To remove: ' + (toRemove.length ? toRemove.map(e => e.projectId).join(', ') : '(none)'));
// Application des changements
if (!dryRun) {
for (const id of toAdd) {
try { await addItem(pr.node_id, id); core.info('Added to ' + id); }
catch(e){ core.error('Add error ' + id + ': ' + e.message); }
}
for (const { itemId, projectId } of toRemove) {
try { await removeItem(itemId, projectId); core.info('Removed from ' + projectId); }
catch(e){ core.error('Remove error ' + projectId + ': ' + e.message); }
}
} else {
core.info('[DRY RUN] No changes');
}
core.endGroup();
}