Je rattrape ma lecture en retard...
J’ai lu la série de posts sur ce problème, que je comprend parfaitement, quand on bosse dans un SI on est surpris de constater à quel point certains devs ou même leur management peuvent s’en b~ l~ c~ d’écrire des tests (étant moi même impliquée, je lutte pour le retour des tests mais personne n’est prêt à remettre en question son confort pour moi. Bande de s~ xD), donc je ne serai pas surprise que cet algo n’ait juste pas été testé ou alors qu’avec uniquement un ou deux voire trois cas nominaux par un QA de bonne volonté :
- personne âgée qui a un rein défaillant
- enfant de 8 ans avec un cœur malade
- personne d’âge moyen mais fumeur
D’ailleurs si aucune couleur de peau n’est définie, quelle valeur prendra cette variable par défaut ? Est-ce vraiment la couleur de peau ou l’ethnie qui est indiquée ?
On pourrait me dire que ce genre d’information ne devrait pas être prise en compte, et honnêtement je n’en sais rien, je ne suis pas médecin. Je suppose qu’en fonction des ethnies, les risques de maladies génétiques ne sont pas les mêmes, et que cette information doit avoir un intérêt, mais très honnêtement je n’en ai aucune certitude, donc je ne vais pas partir dans le procès d’intention, et juste partir du constat que ça existe.
Bref, il serait intéressant de voir comment est foutu le logiciel ! Si c’est un réseau de neurones derrière, alors les gens vont être déçus, c’est le jeu de données étalon en entrée qui a influencé les résultats futurs. Pas de volonté perverse derrière cela. Vu que le réseau de neurones décide tout seul des critères d’affectation, et qu’on a aucun moyen de vérifier les critères qu’il a choisi, il a peut être fait un lien direct implicite noir -> pauvre -> mauvais candidat, puisque les données en entrée l’ont conduit à se calibrer de cette manière (les personnes noires de son jeu de données d’entrée ont été refusés à 80% par exemple - après il faut voir pourquoi, mais ça l’IA s’en moque). Si en plus l’IA a mis en relation pauvre -> drogue ou pauvre -> obésité, alors là c’est mort, t’es foutu.
L’IA n’est pas prête à décider en autonomie sans une revue par un être humain.
Néanmoins je voudrais rajouter un autre point, qui me semble important et qui me dérange dans vos échange avec Lou.
Vous passez votre temps à parler des États-Unis d’Amérique comme si les choses se passaient là-bas comme en France. La lutte des classes est une histoire typiquement Française et la lutte raciale appartient aux E-U. N’apportez pas l’un chez l’autre.
J’ai regardé quelques vidéos d’expatriés noirs américains en France pour voir leur avis, à eux, concernant le traitement des personnes de couleurs.
APARTÉ un peu troll : d’ailleurs je rappelle ce bel effort des universités américaines, qui ont classé les ethnies et considèrent que les ressortissants maghrébins, les personnes des Émirats Arabes Unis, et les asiatiques sont blancs (moi ça ne me dérange pas, à voir ce que pensent les concernes, se sentent-ils privilégiés ?). D’ailleurs les espagnols et les portugais sont blancs aussi, mais les mexicains sont latinos... MAIS ARRÊTEZ DE CLASSER LES GENS BON SANG ! Ça n’a aucun sens...
Source : un serbe sur YouTube xD https://m.youtube.com/watch?v=0c4cf6JkSnc
Bref, je reviens aux témoignages des personnes noires Américaines à Paris. Je retiens plusieurs choses :
-
Aux US le sentiment communautaire noir est très développé (ils se saluent dans la rue sans se connaître par exemple)
-
À Paris, ils n’ont pas réussi à créer des groupes de rencontres dédiés aux personnes noires, personne n’était intéressé (pourquoi ? Apparemment parce que les personnes noires en France viennent de beaucoup d’endroit, Gabon, Sénégal, ... et ne se sentent pas proches les uns des autres, là ou, aux US, l’immigration noire est moins facile du fait de la distance. Les noirs américains sont souvent issus d’une même histoire)
-
Aux US, les personnes restent énormément entre communauté. La personne de la vidéo (que j’ai mis ci-dessous pour référence) dit même que les noirs Américains se sont « self-segregated » (ségrégués eux-mêmes)
-
À Paris, les expatriés noirs ont eu le sentiment d’être égaux aux autres personnes, et même, les petites attentions communautaires leur ont un peu manqué (je comprend c’est chouette d’appartenir à une famille)
Bref l’une des vidéo que j’ai trouvé intéressante sur le sujet, et que je vous partage :
https://m.youtube.com/watch?v=HNiWNfzP1sw
Donc je comprend le souhait de se rattacher à quelque chose que l’on connaît mais :
- les personnes noires en France ne sont pas de la même origine que les noirs Américains et il y a de fortes chances que leurs soucis à eux soient liés à la pauvreté.
- les personnes noires aux US sont dans des communautés actives, et ils y a des fortes chances que les problèmes de ségrégation là-bas soient différent du contexte français.
Donc je pense qu’il serait intéressant d’éviter de ramener les problèmes américains en France et les problèmes France aux US (de toutes façons, la plupart des américains ne savent même pas que l’on existe, sauf pour les marques de luxe).
Prenez soin de vous, et mangez des légumes !
Allez on le note, on sait jamais...
1.Generate keystore(At server):
keytool -genkey -alias bmc -keyalg RSA -keystore KeyStore.jks -keysize 2048
2.Generate new ca-cert and ca-key:
openssl req -new -x509 -keyout ca-key -out ca-cert
3.Extracting cert/creating cert sign req(csr):
keytool -keystore KeyStore.jks -alias bmc -certreq -file cert-file
4.Sign the “cert-file” and cert-signed wil be the new cert:
openssl x509 -req -CA ca-cert -CAkey ca-key -in cert-file -out cert-signed -days 365 -CAcreateserial -passin pass:yourpass
5.importing the ca-cert to keystore file:
keytool -keystore KeyStore.jks -alias CARoot -import -file ca-cert
6.import cert-signed to keystore:
keytool -keystore KeyStore.jks -alias bmc -import -file cert-signed
7.Copy ca-cert into client machine and generate truststore: (At client)
keytool -keystore truststore.jks -alias bmc -import -file ca-cert
8.Copy ca-cert into client machine and generate truststore: (At server)
keytool -keystore truststore.jks -alias bmc -import -file ca-cert-c
Plutôt que PhantomJS, passer à Puppeter.
Ca marche mieux... En fait ça télécharge chromium lol
Moi ce que je voudrais, c'est pouvoir définir MES valeurs par défaut pour mon application Spring-Boot, que je pourrais surcharger avec un fichier properties.
Donc, je veux surcharger programmatiquement les valeurs par défault de Spring-Boot, et quand même permettre la surcharge par fichier. Dans l'idée, ça marche :
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertiesPropertySource;
import java.util.Properties;
@Configuration
@PropertySource(value = "classpath:application.properties", ignoreResourceNotFound = true)
public class DatabaseConfiguration {
private static final Logger LOGGER = LoggerFactory.getLogger(DatabaseConfiguration.class.getCanonicalName());
public static final String DATABASE_URL = "jdbc:h2:./db/dbfile;MODE=MySQL;";
public static final String DATABASE_USER = "sa";
public static final String DATABASE_DRIVER = "org.h2.Driver";
public static final String DATABASE_SCHEMA = "PUBLIC";
@Autowired
private Environment env;
@Value("${spring.datasource.url:}") // Defaulted with empty value
private String databaseUrl;
@Value("${spring.datasource.username:}") // Defaulted with empty value
private String databaseUser;
@Value("${spring.datasource.password:}") // Defaulted with empty value
private String databasePassword;
@Value("${spring.datasource.driver-class-name:}") // Defaulted with empty value
private String databaseDriver;
@Value("${spring.datasource.schema:}") // Defaulted with empty value
private String databaseSchema;
private void overrideProperty(String name, String currentValue, String defaultValue) {
if (currentValue == null || currentValue.isEmpty()) {
currentValue = defaultValue;
ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) this.env;
PropertiesPropertySource propertySource = (PropertiesPropertySource) configurableEnvironment.getPropertySources().get("myProps");
Properties myProperties = new Properties();
if (propertySource != null) {
for (String propertyName : propertySource.getPropertyNames()) {
myProperties.put(propertyName, propertySource.getProperty(propertyName));
}
}
myProperties.put(name, currentValue);
configurableEnvironment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", myProperties));
System.out.println("Property " + name + " not found and defaulted to => " + currentValue);
} else {
System.out.println("Property unchanged " + name + " => " + currentValue);
}
}
/**
* I swear to you, I tried to override configuration !!!
*/
@Bean
public void defaultConfiguration() {
this.overrideProperty("spring.datasource.url", this.databaseUrl, DATABASE_URL);
this.overrideProperty("spring.datasource.jdbc-url", this.databaseUrl, DATABASE_URL);
this.overrideProperty("spring.datasource.user", this.databaseUser, DATABASE_USER);
this.overrideProperty("spring.datasource.driver-class-name", this.databaseDriver, DATABASE_DRIVER);
this.overrideProperty("spring.datasource.schema", this.databaseSchema, DATABASE_SCHEMA);
}
}
Mais mon script s'exécute après la création de la DataSource et pas moyen de l'exécuter avant tout le reste T__T
Faut je creuse encore...
In a Groovy class:
private final Script script;
public MyClass(Script script) {
this.script = script;
}
public myMethod() {
this.script.env.test = "prout"
this.script.println(this.script.env.test)
this.script.properties([
this.script.parameters([
this.script.string(defaultValue: "${MY_VALUE}", description: 'the value', name: "${the_name}", trim: true),
this.script.password(defaultValue: "${MY_PASSWORD}", description: 'the password', name: "${the_password}", trim: true)
])
])
}
In the pipeline:
stage('My Stage') {
steps {
script {
MyClass toto = MyClass(this);
toto.myMethod();
}
}
}
Mais qu’est-ce qu’on attend ?!
Snoop doggy dog !
Des poneys c’est mieux que des petites vaches !
Le Jenkinsfile utilisé :
pipeline {
agent {
node { label 'With-Ansible' }
}
environment {
VM_CREDENTIALS = credentials('my-vm-credentials')
VM_USER = "${VM_CREDENTIALS_USR}"
VM_KEY = "${VM_CREDENTIALS_PSW}"
HOST_NAME = "my-vm-host"
}
stages {
stage('PING MACHINE') {
steps {
script {
println " ========== PING ${HOST_NAME} ========== "
sh "ansible all -i ${HOST_NAME}, -m ping -u ${VM_USER} --extra-vars=\"ansible_ssh_pass=${VM_KEY} ansible_connection=ssh ansible_port='22' ansible_ssh_common_args='-o StrictHostKeyChecking=no'\""
}
}
}
}
}
Il faut laisser la virgule :)
Y a-t-il vraiment des gens qui s’indignent du fait que les parcs - attendez on m’indique que c’est le seul parc ouvert à paris - donc que le seul parc de Paris accessible soit blindé de monde ?
Je pose la question : avez vous dans votre entourage quelqu’un qui annonce changer de jeans toutes les semaines ? Nettoyer son costume toutes les semaines ? Garder les mêmes chaussettes deux jours de suite ?
Vous ne voyez pas le rapport ?
Et si maintenant je vous dit que que les masques de protection ne sont pas distribués aux français mais vendus par les supermarchés ?
J’ai vu une enseigne vendre les 5 masques 30€ (oui mais l’imprimé etait trop joli hin hin).
À ce prix, votre connaissance qui change peu de vêtement parce que « nan mais ça sent pas », il va en acheter combien, des masques ? Un ? Allez peut être deux...
Combien de fois par jour va-t-il changer de masque ? Combien de fois par semaine ? À quelle fréquence va-t-il les laver ?
Et puis il va aller travailler, au même endroit que vous, après avoir pris la ligne 13 du métro, qui est toujours bondée.
Quel est le plus risqué : être ensemble dans un parc sans masque ou serrés dans le métro avec des masques souillés ?
Pour moi c’est exactement pareil.
Déconfiner sans tester et sans distribuer de masques jetables, c’est accepter une forme de fatalité.
Quitte à porter le même masque tous les jours pour des raisons de coût, autant ne rien porter du tout.
Les gens sont libres d’aller travailler dans des conditions tout sauf sanitaire, mais pas libres d’être tassés dans un parc le week-end.
Je vous rappelle que Castaner n’a pas renvoyé ses enfants a l’école.
Encore un article pour diviser les français.
Hello,
Petite note, pour plus tard.
Supposons que je doive utiliser Confluence et que je veuille un module de vote... Et que cette macro ne soit pas disponible !
Comment faire ?
Dans votre page Confluence, rajoutez un composant "HTML" (macro). Si c'est du JS, bon mettez le à la fin de la page, si c'est du css, mettez-le au début (soyons propres).
Confluence propose JQuery. Il est accessible via le raccourci AJS.xxx.
Si vous avez besoin de stocker des variables, l'API REST Confluence (version > 5.5) permet de stocker des properties.
Attention cependant, les seuls types REST dispos sont GET, POST, DELETE. Pas de PUT, ce qui veut dire qu'à chaque changement, il faut faire un DELETE - POST !
Voici un exemple codé rapidement. Ma property à stocker s'appelle "election" :
<ac:layout-cell>
<ac:structured-macro ac:macro-id="33e368de-3e17-4323-908c-2bb1639febe3" ac:name="html" ac:schema-version="1">
<ac:plain-text-body><![CDATA[
<script type="text/javascript">
AJS.toInit(function() {
var votes= {"votesPourA": 0, "votesPourB": 0};
function deleteElections() {
jQuery.ajax({
contentType: 'application/json',
type: 'DELETE',
url: contextPath + "/rest/api/content/" + AJS.params.contentId + "/property/elections",
success: function(response) {
updateVotes();
},
error: function(error) {
if(error.status== 401 || error.status== 402 || error.status== 403) {
alert("you need to be connected in order to vote")
}
}
});
}
function updateVotes() {
jQuery.ajax({
contentType: 'application/json',
type: 'POST',
url: contextPath + "/rest/api/content/" + AJS.params.contentId + "/property",
data: "{ \"key\" : \"elections\", \"value\" : \""+ JSON.stringify(votes).replace(/"/g, '\\"') +"\" }",
success: function(response) {
retrieveVotes();
},
error: function(error) {
if(error.status== 401 || error.status== 402 || error.status== 403) {
alert("you need to be connected in order to vote")
}
}
});
}
function retrieveVotes() {
jQuery.ajax({
contentType: 'application/json',
type: 'GET',
url: contextPath + "/rest/api/content/" + AJS.params.contentId + "/property/",
success: function(response) {
response.results.forEach(function (item, index) {
if(item.key == "elections") {
votes = JSON.parse(item.value);
AJS.$("#voteAspan").text(votes.votesPourA + ' votes');
AJS.$("#voteBspan").text('votes.votesPourB + ' votes');
}
});
}
});
}
AJS.$("#votePourAButton").click(function() {
votes.votesPourA = votes.votesPourA + 1;
deleteElections();
});
AJS.$("#votePourBButton").click(function() {
votes.votesPourB = votes.votesPourB + 1;
deleteElections();
});
setTimeout(() => { retrieveVotes() }, 2000); // This is because AJS.params.contentId property is not available immediatly.
});
</script>
]]></ac:plain-text-body>
</ac:structured-macro>
</ac:layout-cell>
Désérialiser des objets depuis le JSON vers des entités typées en Typescript est un besoin que l'on peut rencontrer n'importe quand.
Voici ce que je fais de mon côté, afin de pouvoir profiter pleinement des méthodes de mes objets.
Pour un objet simple, ceci suffit :
export class Identity {
public name: string;
public age: number;
public constructor(init?: Partial<Identity>) {
Object.assign(this, init);
}
}
Dès que l'on commence à avoir des collections, il faut ajouter un peu d'intelligence (on part du principe que la classe Adress aura un constructeur qui permet cette initialisation, voir dessous) :
export class Contact {
public adresses: Address[];
public phone: string;
public constructor(init?: Partial<Contact >) {
Object.assign(this, init);
if (init != null) {
this.adresses= init.adresses== null ? [] : init.adresses.map(it => new Address(it));
}
}
}
export class Address{
public city: string;
public constructor(init?: Partial<Address>) {
Object.assign(this, init);
}
}
Si on a des "nested objects", donc des classes qui ont d'autres classes en attribut, on fait comme ceci :
export class Person {
public identity: Identity;
public contact: Contact;
public constructor(init?: Partial<Person>) {
Object.assign(this, init);
if (init != null) {
this.identity= init.identity== null ? null : new Identity(init.identity);
this.contact= init.contact== null ? null : new Contact(init.contact);
}
}
}
Et enfin, comment on s'en sert - dans les grandes lignes (passke quand même, hein !):
return this.http.get(`/api/person/${personId}`)
.toPromise()
.then((response: any) => new Person(JSON.parse(response)) );
Il y a des jours comme ça, dans notre existence, où l'on se prend à rêver à une autre vie... Et oui, aujourd'hui on m'a demandé de rédiger un tuto sur comment utiliser Liquibase. T_____T
Du coup, je vais noter ici tout ce que je trouve vraiment regrettable concernant cette techno :
- La documentation sur le site officiel est vraiment bâclée. Le "Get Started" ne donne même pas un "Hello World".
- La classe de base ne permet pas l'usage d'une DataSource existante directement
- La documentation officielle encourage les développeurs à écrire leurs scripts de migration de base en XML. Quand je lis ceci :
<changeSet id="1" author="bob"> <createTable tableName="testTable"> <rollback> <dropTable tableName="testTable"/> </rollback> </changeSet>
Je me demande tout de suite, et si jamais je dois lancer mes scripts sans Liquibase ?
- Je mentionne rapidement la promesse du rollback qui ne vaut que si tu appliques des méthodes Crafts sur ta gestion de base, et dans ce cas, ils ne servent plus à rien (que fait-on si le script de rollback plante ? Comment fait-on un rollback d'un drop de données ?).
- Le XML, bon sang, LE XML ! Mais pourquoi ?! (référence : DOOOOOOOM ! MOTHERFUCKING DOOM !)
J'agrandirai la liste avec mes nouvelles remarques. En attendant je recommande Flyway <3
Anecdote : Pour appeler un job local, le step s'appelle "build", mais pour appeler un job distant c'est triggerRemoteJob... C'est quand même pas très homogène...
Ce job appelle un autre job en passant des paramètres :
pipeline {
stages {
...
stage('TRIGGER OTHER JOB') {
steps {
script {
println " ========== TRIGGER NEXT JOB ========== "
build job: 'other-job/master', parameters: [[$class: 'StringParameterValue', name: 'PROUT', value: "TRUC" ]]
}
}
}
}
}
Ce job récupère des paramètres :
pipeline {
parameters {
string(name: 'PROUT', defaultValue: 'VALUE', description: 'Received from previous job')
}
stages {
stage('HELLO WORLD') {
steps {
script {
println " ========== HELLO WORLD II WITH ${PROUT} ========== "
}
}
}
}
}
Allez, je me permet de donner mon avis sur la gestion du COVID et l'efficacité des mesures prises.
Ne pas confondre Confinement et Quarantaine
Si la quarantaine est efficace pour limiter la contagiosité, le confinement est complètement inefficace pour y arriver.
La quarantaine consiste à retirer d'un système les individus identifiés comme suspicieux et à les placer dans un espace clos limitant les risques de transmettre la maladie. Ensuite, sous supervision de personnes formées et compétentes, l'évaluation de l'état de santé des personnes infectées permettra de décider si oui ou non, elles sont aptes à se réintégrer au système sans risque.
Le confinement consiste à demander à tout le monde de limiter ses contacts avec l'extérieur, sans savoir qui est porteur sain, malade, en rémission ou non touché. Du coup, c'est à l'estimation de chacun, sans test, sans supervision, d'estimer si elles sont "capables" de sortir acheter leur baguette de pain.
Bullshit numéro 1: penser que le confinement est efficace ou sert à quelque chose. Le plus probable c'est que tout le monde l'attrape, en étalant les malades sur la durée, en priant qu'une immunité se créé, ce qui est encore largement à démontrer.
Autant remettre tout le monde dehors, ça ira plus vite. Si le souhait est de ne rien gérer, ça sera plus efficace. On meurt libre et entouré, c'est quand même plus humain que les enterrements par Skype.
Le calcul du taux de mortalité - mais sans tester la population
X% de mortalité sans tester personne, mais ça veut dire quoi ?!
Les gens sont uniquement testés en hôpital, suite à leur propre prise de décision de se déplacer, en supposant que l'appel au médecin traitant et la médicamentation ne suffisaient pas.
Je pose la question, et là pour le coup, ça me semble pertinent : Par rapport aux autres virus, pour ceux qui se déplacent parce que l'appel au médecin et la médicamentation ne suffisent pas, combien décèdent ?
Bullshit numéro 2 : un taux de mortalité basé sur finalement pas grand monde et comparable avec rien du tout mais qu'on étale au visage à longueur de temps
Le taux de mortalité - mais sans savoir les critères nécessaires pour y être comptabilisé
Prenons un cas très spécifique : Jean, qui a un cancer des poumons, mais qui a la chance d'être porteur asymptomatique du COVID19. Il se rend à l’hôpital car il souffre de détresse respiratoire suite à une complication de son cancer. Le test au COVID 19 se révèle positif, puisqu'il est porteur sain. Il décède quelques jours plus tard de son cancer (RIP Jean).
Sera-t-il comptabilisé dans la mortalité COVID19 ? Impossible de trouver l'info.
Bullshit numéro 3 : Pas d'explication du protocole médical ou scientifique des calculs de comptabilisation
Penser que le confinement limite les déplacements des individus
Certes, une bonne partie de la population ne se rend plus sur son lieu de travail. Mais puisqu'une bonne partie des commerces sont fermés, et que les employés ont le droit de poser leur droit de retrait, les confinés sont parfois obligées de prendre les transports en commun ou d'aller plus loin pour accéder à un besoin disponible à côté de chez eux auparavant. <a href="?addtag=NoPQ" title="Hashtag NoPQ">#NoPQ</a>
Bullshit numéro 4 : Puisque tout le monde doit se démerder pour envoyer sa paperasse administrative à temps et que beaucoup de postes ont fermé, les gens se déplacent plus loin !
Finalement, la limitation de la contagion ne fait uniquement parce que les employés profitent de leur télétravail pour ré-organiser leur agenda et ne sortent pas tous au même moment, le samedi ou le dimanche.
Hi hi !
Le racisme aujourd'hui
Je lisais ce post d'Antichesse, un peu plus tôt, et je me suis dit que j'allais dire quelque chose. allez, comme ça, c'est gratuit (donc c'est vous le produit ;) )
Je suis très intéressée par cette idée du "racisme systémique", et l'idée selon laquelle insulter quelqu'un de "sale blanc" serait une agression décorrélée du racisme.
Quand on parle de personnes de couleur
Alors déjà, et avant de commencer, je dois dire que l'idée de "personne de couleur", me laisse un peu perplexe. J'ai beaucoup de difficulté à mettre les gens dans des cases de couleur... Est-ce que machin est noir ou est-ce qu'il est pas trop noir ? Est-ce qu'il est chocolat... Peut-être parce que je suis une fille, et que les vendeuses de chez Sephora m'ont expliqué très tôt que le fond de teint se distinguait selon deux axes : teint beige - rosé - olive - doré d'un côté, pigmentation de la peau d'un autre côté. Et attention n'achetez pas votre fond de teint en mars pour septembre, vous risqueriez de bronzer et la couleur ne vous irait plus !
Donc ce que j'ai retenu :
- Ben quand tu bronzes, tu changes de couleur. (waow ! incroyable ! such innovation ! such nouveauté ! Amazing !)
- Le fond de teint en base beige ne va pas aux personnes en base rose. Donc on peut être blanc rose ou blanc beige, et on a pas la même couleur.
La marque Sephora s'est même vantée de proposer 57 teintes différentes de fond de teint ! Et c'est nécessaire ! Parce que sinon ça change la couleur de la peau !
Donc partons de la base que répartir les gens en "couleur", ça revient à prendre les 57 teintes et à faire des catégories, ce que je trouve légèrement contre-intuitif. Donc j'aime pas trop la notion de "personne de couleur", parce que Sephora a l'air de dire qu'on a au moins 57 couleurs différentes minimum, et les fonds de teint blanc ou noir, ça existe pas. Ca va être un 23 beige naturel ou 23.5 naturel rosé, un 44 praline doré ou un 45 café latté...
Paye ton insulte... "hé espèce de sale praline doré !"... Ça va en faire des gens qui se haïssent sur le critère de la couleur...
Quand on parle de racisme systémique
Le racisme comme oppression systémique est l'idée selon laquelle les personnes répondant à un stéréotype de couleur subissent une distinction de considération issue du système. Je ne sais pas si je l'ai bien écrit. Ok, soit, admettons, je peux l'entendre. Par exemple, dans un pays dont la loi est différente en fonction de critères arbitraires (couleur - religion - sexe), on a en effet une oppression systémique.
__ Remarquez que je dis sexe et pas genre. En effet, il semblerait que les français aient oublié que le sens premier de "genre" est "catégorie", exactement comme un genre littéraire ou un genre d'individu. A l'inverse, aux USA, Gender se traduit littéralement par "Sexe". Les faux amis ont encore frappé...__
Maintenant, ce qui me gène c'est l'idée que le racisme ne soit que l'expression d'une oppression systémique, et donc que le fait de dire "sale blanc" ne soit pas raciste.
Pourquoi le fait de traiter quelqu'un de "sale blanc" ne serait pas du racisme ? Hé bien, si j'ai bien compris, parce que ce racisme ne serait pas l'expression d'une oppression systémique, nouvelle définition du racisme.
Donc devant deux situations similaires : une personne qui en insulte une autre de "sale noir" - une personne qui en insulte une autre de "sale blanc" = Devant ce même délit, le jugement n'est pas le même. Dans un cas, c'est du racisme, et dans l'autre une agression, et la justice assigne des peines différentes aux deux cas.
Il en ressort un système où les individus sont traités différemment selon des critères arbitraires (couleur - religion - sexe), c'est donc un système paradoxal.
Cela risque d'entretenir la haine de l'autre pour sa différence, et d'accentuer les différences de jugement. Donc en plus, il s'entretient.
J'en connais quelques uns, des systèmes construits sur des paradoxes :
- Le communismes, mais avec une oligarchie qui centralise les richesses
- Le capitalisme libéral, mais avec un renflouement de certains business par l’État
- Le fait que tu aies besoin d'un Kadabra pour compléter ton pokédex, mais qu'après l'échange, tu reçoives un Alakazam
En général, les lois qui ne sont pas valides avec elle-mêmes sont fausses. Elles contiennent un mensonge.
Donc oui, bien sûr, l'oppression systémique c'est mal ! Juger quelqu'un pour quelque chose qu'il n'a pas choisi comme sa couleur, son sexe ou sa religion, c'est nul !
Mais se créer un système qui re-créer une distinction de droits en fonction de ces critères arbitraire, ça ne peut pas être la solution.
En faisant ça, on entretient la haine le l'autre, et quand on fait croire aux gens que droite = racisme, on joue le jeu du Rassemblement National.
Mais heureusement, il y aura toujours un candidat dont personne ne veut pour se lever face au racisme et à l’extrême droite ! Mais ça vous coûtera vos congés ! ;D
Hello Antichesse, tu m'as dit que tu allais peut-être t'intéresser à la remontée du coverage côté Front vers Sonar, donc je te met des infos sur ce que j'ai fait, pour t'aider.
Infos préalables (mais je sais que ça marche avec Angular et depuis Karma 4.1.0) :
Package.json
"devDependencies": {
"@angular-devkit/build-angular": "0.901.0",
"@angular/cli": "9.1.0",
"@angular/compiler-cli": "9.1.0",
"@angular/language-service": "9.1.0",
"@types/jasmine": "3.5.10",
"@types/jasminewd2": "2.0.8",
"@types/node": "12.12.34",
"codelyzer": "5.2.2",
"jasmine-core": "3.5.0",
"jasmine-spec-reporter": "4.2.1",
"karma": "4.4.1",
"karma-coverage-istanbul-reporter": "2.1.1",
"karma-firefox-launcher": "1.3.0",
"karma-jasmine": "3.0.3",
"karma-jasmine-html-reporter": "1.5.3",
"protractor": "5.4.3",
"ts-node": "8.3.0",
"tslint": "6.1.1",
"typescript": "3.8.3"
},
Alors déjà, je lance mes tests en Firefox Headless.
Extrait de mon fichier Karma.conf.js :
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-firefox-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
...
browsers: ['FirefoxHeadless'],
captureTimeout: 600000,
browserDisconnectTolerance: 3,
browserDisconnectTimeout: 600000,
browserNoActivityTimeout: 600000,
customLaunchers: {
FirefoxHeadless: {
base: 'Firefox',
flags: ['-headless', '--no-sandbox']
}
}
...
});
};
Mais surtout, dans le fichier Karma, il y a un élément super important, l'emplacement de stockage de ton coverage :
Karma.conf.js
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/project-name'), **<---- ICI**
reports: ['html', 'lcovonly', 'text-summary'], <--- Lcov doit être inclu aussi !
fixWebpackSourcePaths: true
},
Le dir indique ou le coverage sera stocké. Tu en auras besoin dans ton fichier JenkinsFile. Pour moi, à la racine de mon WORKSPACE, j'aurais un dossier "coverage", qui contient un autre dossier "project-name" contenant le résultat de l'analyse Istanbul-reporter, incluant le coverage.
Voici quelques extraits de mon fichier JenkinsFile, pour montrer les modifs que j'ai du faire :
pipeline {
agent { label 'trololo-pouetpouet' }
stages {
stage('Clone source code') {
steps {
git branch:'${BRANCH_NAME}', credentialsId: gitCredentialsId, url: gitSshUrl
}
}
stage('Test') {
steps {
println " ========== START PLAYING TESTS ========== "
configFileProvider([configFile(fileId: 'npm-npmrc', targetLocation: '/root/.npmrc')]) {
sh "export SASS_BINARY_PATH=${sassBinaryLocation}/${bindingNodeFileName} ; npm run test-prod"
}
stash includes: 'coverage/**/*', name: 'COVERAGE' **<---- Ici, c'est parce que je change d'agent, donc je garde l'output de mon coverage **
}
}
stage('Build') {
steps {
println " ========== START BUILDING DELIVERABLE ========== "
...
}
}
stage('Sonarqube analysis') {
agent {
label 'sonar-scanner-agent-de-ouf'
}
steps {
git branch:'${BRANCH_NAME}', credentialsId: gitCredentialsId, url: gitSshUrl
script {
configFileProvider([configFile(fileId: 'npm-npmrc', targetLocation: '/root/.npmrc')]) {
...
unstash 'COVERAGE' ** <----- je récupère mon output d'analyse incluant mon coverage **
withSonarQubeEnv(sonarEnvName) {
sh "sonar-scanner "+
"-Dsonar.verbose=true "+
"-Dsonar.projectBaseDir=${WORKSPACE} "+
"-Dsonar.projectVersion=${taggedVersion} "+
"-Dsonar.sources=. "+
"-Dsonar.exclusions='**/*.spec.ts, **/*.js, src/test/*'"+ **<---- Ici, j'exclue les tests et le js du coverage et de l'analyse **
"-Dsonar.projectName='${binaryName}' "+
"-Dsonar.projectKey=${binaryName} "+
"-Dsonar.typescript.lcov.reportPaths=${env.WORKSPACE}/coverage/project-name/lcov.info "+ <---- Ici, il faut indiquer le path récupéré depuis le fichier Karma.conf.js, et pointer vers le fichier lcov.info
(env.BRANCH_NAME != 'master' ? "-Dsonar.branch.name=${env.BRANCH_NAME} -X " : "")
}
}
}
}
}
...
}
...
}
Et last, but not least, une petite indication supplémentaire à préciser quand on fait de l'angular :
package.json
"scripts": {
"ng": "ng",
...
"test": "ng test --watch --code-coverage", ** <---- Indiquer que l'on veut l'emission du coverage !**
"test-prod": "npm install && ng test --code-coverage",
"lint": "ng lint",
"e2e": "ng e2e"
},
Et voilà, ton coverage est dispo sur SONAR !
Si quelque n'est pas clair, n'hésite pas à me le dire !
A tester ! :)
Hello Animal,
Autant j’aime l’idée que le Dr.Raoult soit en lutte contre, d’une part un délit de faciès (depuis quand appeler quelqu’un Gandalf parce qu’il a un style personnel est quelque chose de correct ?!), mais aussi des magouilles du gouvernement.
Autant il faut admettre que son protocole expérimental est un peu léger, et qu’il a exclu des résultats les individus qui répondaient mal au traitement. Notamment celui qui est mort (anecdotique ?).
Parmi ses sponsors privés se trouve le groupe pharmaceutique qui distribue la chloroquine.
Encore une histoire en nuances de gris...
Aujourd'hui j'ai appris comment combiner des observables pour attendre que tous les traitements s'exécutent.
Et c'est surtout grâce au lien.
En même temps, la doc RXJS est pas mal non plus : https://www.learnrxjs.io/learn-rxjs/operators/combination/combinelatest