How to group many information une one select
What you are trying to do is called pivoting. You essentially want the results grouped by code and action but re-arranged so that instead of one row per code and action you get one row per code only, all the distinct action values (well, just two in your case) forming separate columns.

In other words, instead of


action   code  value
-------  ----  ------
action1  IN    value1
action1  OUT   value2
action2  IN    value3
...      ...   ...


you are trying to get


action   IN      OUT
-------  ------  ------
action1  value1  value2
action2  value3  ...
...      ...     ...


Some SQL products support a dedicated PIVOT syntax. MySQL is not one of them, but you can use other ways.

One common way is conditional aggregation. You will group the rows by code only, because you want one row per code in the output. The aggregation by action will be achieved by introducing a conditional as the aggregate function's argument. This is how you code that in SQL:

SELECT
  art.id,
  art.art_code,
  art.art_name,
  SUM(CASE act.action WHEN 'IN'  THEN act.qte END) AS `IN`,
  SUM(CASE act.action WHEN 'OUT' THEN act.qte END) AS `OUT`
FROM
  article AS art
  LEFT JOIN action AS act ON art.art_code = act.code
GROUP BY
  art.id,
  art.art_code,
  art.art_name
ORDER BY
  art.id ASC
;


Each SUM expression aggregates qte just for one of the action values, either 'IN' or 'OUT', using a CASE expression. As shown in the query, you need two SUM expressions, one per each value of action. If you had more, you would need to add more SUMs accordingly.

However, as there only two values here, it may make sense to try alternative methods. One such alternative is in Akina's answer. Here is another option:

SELECT
  art.id,
  art.art_code,
  art.art_name,
  act_in.`IN`,
  act_out.`OUT`
FROM
  article AS art

  LEFT JOIN
  (
    SELECT code, SUM(qte) AS `IN`  FROM action WHERE action = 'IN'  GROUP BY code
  ) AS act_in
  ON art.art_code = act_in.code

  LEFT JOIN
  (
    SELECT code, SUM(qte) AS `OUT` FROM action WHERE action = 'OUT' GROUP BY code
  ) AS act_out
  ON art.art_code = act_out.code

ORDER BY
  art.id ASC
;


As you can see, getting each of the two columns (IN and OUT) requires one outer join to a derived table containing the aggregated results for the corresponding action value. It is easy to see how this approach would not be a good idea if you needed to produce ten such columns. Not only would the query itself become cumbersome much more quickly than the conditional aggregation method, but the performance would deteriorate very soon too. However, for just two columns this option might be worth a shot.

Both suggestions presented in this answer can be found and played with at dbfiddle.uk (the setup was borrowed from Akina's fiddle):